diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 6699a86..bb90705 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -20,6 +20,8 @@
 #ifndef _DB_H
 #define _DB_H
 
+#include <stdbool.h>
+
 #include "gsm_subscriber.h"
 
 struct gsm_equipment;
@@ -35,13 +37,15 @@ int db_prepare(void);
 int db_fini(void);
 
 /* 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, bool alloc_exten);
 struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field,
 					 const char *subscr);
 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_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_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
 int db_subscriber_delete(struct gsm_subscriber *subscriber);
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 4844412..8fbb26e 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -24,6 +24,7 @@ enum gsm_subscr_ext_alloc_policy {
 	GSM_SUBSCR_DONT_CREATE = 0,
 	GSM_SUBSCR_RANDOM_EXT = 1,
 	GSM_SUBSCR_MATCH_PREF = 2,
+	GSM_SUBSCR_NO_EXT = 4
 };
 
 enum gsm_security_event {
@@ -293,6 +294,8 @@ struct gsm_network {
 
 	/* subscriber related features */
 	int create_subscriber;
+	uint64_t ext_min;
+	uint64_t ext_max;
 	struct gsm_subscriber_group *subscr_group;
 	struct gsm_sms_queue *sms_queue;
 
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 7108bff..3fabb63 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -1,6 +1,8 @@
 #ifndef _GSM_SUBSCR_H
 #define _GSM_SUBSCR_H
 
+#include <stdbool.h>
+
 #include "gsm_data.h"
 #include <osmocom/core/linuxlist.h>
 
@@ -90,7 +92,8 @@ enum gsm_subscriber_update_reason {
 struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
 struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
 struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
-						const char *imsi);
+						const char *imsi, uint64_t smin,
+						uint64_t smax, bool ext);
 struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp,
 					  uint32_t tmsi);
 struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp,
diff --git a/openbsc/src/libbsc/net_init.c b/openbsc/src/libbsc/net_init.c
index ed23f33..9d47698 100644
--- a/openbsc/src/libbsc/net_init.c
+++ b/openbsc/src/libbsc/net_init.c
@@ -105,7 +105,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->mncc_recv = mncc_recv;
-
+	net->ext_min = GSM_MIN_EXTEN;
+	net->ext_max = GSM_MAX_EXTEN;
 	gsm_net_update_ctype(net);
 
 	return net;
diff --git a/openbsc/src/libcommon/gsm_subscriber_base.c b/openbsc/src/libcommon/gsm_subscriber_base.c
index a455824..5f0a1be 100644
--- a/openbsc/src/libcommon/gsm_subscriber_base.c
+++ b/openbsc/src/libcommon/gsm_subscriber_base.c
@@ -60,6 +60,7 @@ struct gsm_subscriber *subscr_alloc(void)
 	llist_add_tail(&s->entry, &active_subscribers);
 	s->use_count = 1;
 	s->tmsi = GSM_RESERVED_TMSI;
+	s->extension[0] = '\0';
 
 	INIT_LLIST_HEAD(&s->requests);
 
diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c
index 9ac39de..3fd8d0b 100644
--- a/openbsc/src/libmsc/ctrl_commands.c
+++ b/openbsc/src/libmsc/ctrl_commands.c
@@ -18,6 +18,9 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
+
+#include <stdbool.h>
+
 #include <osmocom/ctrl/control_cmd.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_subscriber.h>
@@ -83,6 +86,8 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
 	char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL;
 	struct gsm_subscriber* subscr;
 	int rc;
+	bool ext = (GSM_SUBSCR_RANDOM_EXT & net->create_subscriber) ? true :
+		false;
 
 	tmp = talloc_strdup(cmd, cmd->value);
 	if (!tmp)
@@ -95,7 +100,9 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
 
 	subscr = subscr_get_by_imsi(net->subscr_group, imsi);
 	if (!subscr)
-		subscr = subscr_create_subscriber(net->subscr_group, imsi);
+		subscr = subscr_create_subscriber(net->subscr_group, imsi,
+						  net->ext_min,
+						  net->ext_max, ext);
 	if (!subscr)
 		goto fail;
 
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 267b5ef..c2a956d 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -23,6 +23,7 @@
 #include <inttypes.h>
 #include <libgen.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -500,7 +501,8 @@ int db_fini(void)
 	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, bool alloc_exten)
 {
 	dbi_result result;
 	struct gsm_subscriber *subscr;
@@ -532,7 +534,8 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi)
 	strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
 	dbi_result_free(result);
 	LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi);
-	db_subscriber_alloc_exten(subscr);
+	if (alloc_exten)
+		db_subscriber_alloc_exten(subscr, smin, smax);
 	return subscr;
 }
 
@@ -937,8 +940,11 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
 
 	dbi_conn_quote_string_copy(conn, 
 				   subscriber->name, &q_name);
-	dbi_conn_quote_string_copy(conn, 
-				   subscriber->extension, &q_extension);
+	if (subscriber->extension[0] != '\0')
+		dbi_conn_quote_string_copy(conn,
+					   subscriber->extension, &q_extension);
+	else
+		q_extension = strdup("NULL");
 	
 	if (subscriber->tmsi != GSM_RESERVED_TMSI) {
 		sprintf(tmsi, "%u", subscriber->tmsi);
@@ -1043,15 +1049,17 @@ int db_subscriber_delete(struct gsm_subscriber *subscr)
 	}
 	dbi_result_free(result);
 
-	result = dbi_conn_queryf(conn,
-			"DELETE FROM SMS WHERE src_addr=%s OR dest_addr=%s",
-			subscr->extension, subscr->extension);
-	if (!result) {
-		LOGP(DDB, LOGL_ERROR,
-			"Failed to delete SMS for %llu\n", subscr->id);
-		return -1;
+	if (subscr->extension[0] != '\0') {
+		result = dbi_conn_queryf(conn,
+			    "DELETE FROM SMS WHERE src_addr=%s OR dest_addr=%s",
+					 subscr->extension, subscr->extension);
+		if (!result) {
+			LOGP(DDB, LOGL_ERROR,
+			     "Failed to delete SMS for %llu\n", subscr->id);
+			return -1;
+		}
+		dbi_result_free(result);
 	}
-	dbi_result_free(result);
 
 	result = dbi_conn_queryf(conn,
 			"DELETE FROM VLR WHERE subscriber_id=%llu",
@@ -1231,13 +1239,14 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber)
 	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;
 	uint32_t try;
 
 	for (;;) {
-		try = (rand()%(GSM_MAX_EXTEN-GSM_MIN_EXTEN+1)+GSM_MIN_EXTEN);
+		try = (rand() % (smax - smin + 1) + smin);
 		result = dbi_conn_queryf(conn,
 			"SELECT * FROM Subscriber "
 			"WHERE extension = %i",
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index ab950c7..e498b6a 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -523,14 +523,19 @@ static int mm_tx_identity_req(struct gsm_subscriber_connection *conn, uint8_t id
 static struct gsm_subscriber *subscr_create(const struct gsm_network *net,
 					    const char *imsi)
 {
+	const char *ap = net->auth_prefix;
+	bool ext = (GSM_SUBSCR_RANDOM_EXT & net->create_subscriber) ? true :
+		false;
+
 	if (GSM_SUBSCR_DONT_CREATE == net->create_subscriber)
 		return NULL;
 
 	if (net->create_subscriber & GSM_SUBSCR_MATCH_PREF)
-		if (!subscr_prefix_check(net->auth_prefix, imsi))
+		if (!subscr_prefix_check(ap, imsi))
 			return NULL;
 
-	return subscr_create_subscriber(net->subscr_group, imsi);
+	return subscr_create_subscriber(net->subscr_group, imsi, net->ext_min,
+					net->ext_max, ext);
 }
 
 /* Parse Chapter 9.2.11 Identity Response */
@@ -582,7 +587,6 @@ static int mm_rx_id_resp(struct gsm_subscriber_connection *conn, struct msgb *ms
 	return gsm0408_authorize(conn, msg);
 }
 
-
 static void loc_upd_rej_cb(void *data)
 {
 	struct gsm_subscriber_connection *conn = data;
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 57c10cf..7d62888 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -203,9 +203,11 @@ void subscr_remove_request(struct subscr_request *request)
 }
 
 struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
-					const char *imsi)
+						const char *imsi, uint64_t smin,
+						uint64_t smax, bool ext)
 {
-	struct gsm_subscriber *subscr = db_create_subscriber(imsi);
+	struct gsm_subscriber *subscr =
+		db_create_subscriber(imsi, smin, smax, ext);
 	if (subscr)
 		subscr->group = sgrp;
 	return subscr;
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 0ac2e90..bf7a947 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -21,6 +21,8 @@
 #include <stdlib.h>
 #include <limits.h>
 #include <unistd.h>
+#include <stdbool.h>
+#include <inttypes.h>
 #include <time.h>
 
 #include <osmocom/vty/command.h>
@@ -235,12 +237,16 @@ DEFUN(subscriber_create,
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
 	struct gsm_subscriber *subscr;
+	bool ext = (GSM_SUBSCR_RANDOM_EXT == gsmnet->create_subscriber) ? true :
+		false;
 
 	subscr = subscr_get_by_imsi(gsmnet->subscr_group, argv[0]);
 	if (subscr)
 		db_sync_subscriber(subscr);
 	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, ext);
 
 		if (!subscr) {
 			vty_out(vty, "%% No subscriber created for IMSI %s%s",
@@ -1031,6 +1037,34 @@ DEFUN(cfg_nitb, cfg_nitb_cmd,
 	return CMD_SUCCESS;
 }
 
+/* Note: limit on the prefix 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_noext, cfg_nitb_subscr_noext_cmd,
+      "subscriber-create-no-extension",
+      "Do not assign extension when creating subscriber on demand.\n")
+{
+	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	gsmnet->create_subscriber |= GSM_SUBSCR_NO_EXT;
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd,
       "subscriber-create-on-demand [imsi-prefix]",
       "Make a new record when a subscriber is first seen.\n"
@@ -1038,9 +1072,11 @@ DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd,
       "authorize-prefix command \n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
-	gsmnet->create_subscriber = GSM_SUBSCR_RANDOM_EXT;
+	if (!gsmnet->create_subscriber)
+		gsmnet->create_subscriber = GSM_SUBSCR_RANDOM_EXT;
 	if (argc)
 		gsmnet->create_subscriber |= GSM_SUBSCR_MATCH_PREF;
+
 	return CMD_SUCCESS;
 }
 
@@ -1079,8 +1115,15 @@ static int config_write_nitb(struct vty *vty)
 		" imsi-prefix" : "";
 
 	vty_out(vty, "nitb%s", VTY_NEWLINE);
-	vty_out(vty, " %ssubscriber-create-on-demand%s%s",
-		pref, ims, VTY_NEWLINE);
+	vty_out(vty, " %ssubscriber-create-on-demand%s%s", pref, ims,
+		VTY_NEWLINE);
+	if (gsmnet->create_subscriber & GSM_SUBSCR_NO_EXT)
+		vty_out(vty, " subscriber-create-no-extension%s", 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",
 		gsmnet->avoid_tmsi ? "no " : "", VTY_NEWLINE);
 	return CMD_SUCCESS;
@@ -1135,6 +1178,8 @@ int bsc_vty_init_extra(void)
 	install_element(CONFIG_NODE, &cfg_nitb_cmd);
 	install_node(&nitb_node, config_write_nitb);
 	install_element(NITB_NODE, &cfg_nitb_subscr_create_cmd);
+	install_element(NITB_NODE, &cfg_nitb_subscr_noext_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_assign_tmsi_cmd);
 	install_element(NITB_NODE, &cfg_nitb_no_assign_tmsi_cmd);
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c
index 6b40e84..1deaf1b 100644
--- a/openbsc/tests/db/db_test.c
+++ b/openbsc/tests/db/db_test.c
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <inttypes.h>
 
 static struct gsm_network dummy_net;
@@ -159,12 +160,13 @@ static void test_sms_migrate(void)
 	subscr_put(rcv_subscr);
 }
 
-static void test_subs(const char *alice_imsi, char *imei1, char *imei2)
+static void test_subs(const char *alice_imsi, char *imei1, char *imei2, bool ext)
 {
 	struct gsm_subscriber *alice = NULL, *alice_db;
         char scratch_str[256];
 
-	alice = db_create_subscriber(alice_imsi);
+	alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN,
+				     ext);
 	db_subscriber_assoc_imei(alice, imei1);
 	if (imei2)
 		db_subscriber_assoc_imei(alice, imei2);
@@ -219,18 +221,22 @@ int main()
 	struct gsm_subscriber *alice_db;
 
 	char *alice_imsi = "3243245432345";
-	alice = db_create_subscriber(alice_imsi);
+	alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN,
+				     true);
 	db_sync_subscriber(alice);
 	alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi);
 	COMPARE(alice, alice_db);
 	SUBSCR_PUT(alice_db);
 	SUBSCR_PUT(alice);
 
-	test_subs("3693245423445", "1234567890", NULL);
-	test_subs("9993245423445", "1234567890", "6543560920");
+	test_subs("3693245423445", "1234567890", NULL, true);
+	test_subs("9993245423445", "1234567890", "6543560920", true);
+	test_subs("3123122223445", "1234567890", NULL, false);
+	test_subs("9123121223445", "1234567890", "6543560920", false);
 
 	/* 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,
+				     true);
 	OSMO_ASSERT(!alice);
 
 	test_sms();
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index e240811..9dd8103 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -422,11 +422,15 @@ class TestVTYNITB(TestVTYGenericBSC):
         self.vty.enable()
 
         imsi = "204300854013739"
+        imsi2 = "204301824913769"
+        imsi3 = "100500854113769"
+        imsi4 = "100583744053769"
         wrong_imsi = "204300999999999"
 
         # Lets create one
         res = self.vty.command('subscriber create imsi '+imsi)
         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])
         res = self.vty.command('subscriber imsi '+imsi+' name '+('X' * 160))
@@ -440,9 +444,54 @@ class TestVTYNITB(TestVTYGenericBSC):
 
         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)
+
+        # Without extension
+        self.vty.command("configure terminal")
+        self.vty.command("nitb")
+        self.assertTrue(self.vty.verify("subscriber-create-no-extension", ['']))
+        self.vty.command("end")
+
+        res = self.vty.command('subscriber create imsi ' + imsi3)
+        self.assert_(res.find("    IMSI: " + imsi3) > 0)
+        self.assertEquals(res.find("Extension"), -1)
+
+        # With extension again
+        self.vty.command("configure terminal")
+        self.vty.command("nitb")
+        self.assertTrue(self.vty.verify("no subscriber-create-on-demand", ['']))
+        self.assertTrue(self.vty.verify("subscriber-create-on-demand", ['']))
+        self.assertTrue(self.vty.verify("subscriber-create-on-demand random 221 666", ['']))
+        self.vty.command("end")
+
+        res = self.vty.command('subscriber create imsi ' + imsi4)
+        self.assert_(res.find("    IMSI: " + imsi4) > 0)
+        self.assert_(res.find("    Extension: ") > 0)
+
         # Delete it
         res = self.vty.command('subscriber delete imsi '+imsi)
         self.assert_(res != "")
+        res = self.vty.command('subscriber delete imsi ' + imsi2)
+        self.assert_(res != "")
+        res = self.vty.command('subscriber delete imsi ' + imsi3)
+        self.assert_(res != "")
+        res = self.vty.command('subscriber delete imsi ' + imsi4)
+        self.assert_(res != "")
 
     def testShowPagingGroup(self):
         res = self.vty.command("show paging-group 255 1234567")
