summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Chemeris <Alexander.Chemeris@gmail.com>2013-10-03 01:43:49 -0400
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2013-10-06 23:37:05 +0200
commit59189e37b8c8715dfddfde7494e40e1b36bb919f (patch)
tree0e40c7028936b3cca2904765cb212b6003f9afbe
parent5f3218ea68ba71145e171be5f06015651a081e1e (diff)
Initial implementation of an external number alias for a subscriber.
This allows user to have an internal short number, while having an external globally routable MSISDN at the same time. If external_number is set for a user, it will be used for all communications outside our network instead of the internal extension. At this moment it is used only by incoming/outgoing SMPP SMS.
-rw-r--r--openbsc/include/openbsc/db.h1
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h9
-rw-r--r--openbsc/src/libbsc/bsc_vty.c3
-rw-r--r--openbsc/src/libmsc/db.c33
-rw-r--r--openbsc/src/libmsc/gsm_subscriber.c3
-rw-r--r--openbsc/src/libmsc/sip_sms.c1
-rw-r--r--openbsc/src/libmsc/smpp_openbsc.c2
-rw-r--r--openbsc/src/libmsc/vty_interface_layer3.c3
-rw-r--r--openbsc/tests/db/db_test.c109
9 files changed, 131 insertions, 33 deletions
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 25c2aea70..e015a18ae 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -44,6 +44,7 @@ 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_assoc_extern_number(struct gsm_subscriber *subscriber, char *extern_number);
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_sync_equipment(struct gsm_equipment *equip);
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 1b74256cd..58b280bdd 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -43,6 +43,15 @@ struct gsm_subscriber {
uint16_t lac;
char name[GSM_NAME_LENGTH];
char extension[GSM_EXTENSION_LENGTH];
+ /* Optional: an external phone number alias.
+ *
+ * This allows user to have an internal short number, while having an
+ * external globally routable MSISDN at the same time.
+ * If external_number is set for a user, it will be used for all
+ * communications outside our network instead of the internal extension.
+ *
+ * PS At this moment it is used only by incoming/outgoing SMPP SMS. */
+ char external_number[GSM_EXTENSION_LENGTH+1];
int authorized;
time_t expire_lu;
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index e41d4de4c..90c7e3464 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -964,6 +964,9 @@ static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
if (subscr->extension)
vty_out(vty, " Extension: %s%s", subscr->extension,
VTY_NEWLINE);
+ if (strlen(subscr->external_number))
+ vty_out(vty, " External number: %s%s", subscr->external_number,
+ VTY_NEWLINE);
vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
if (subscr->tmsi != GSM_RESERVED_TMSI)
vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 9a8cd886b..d71a6b142 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -61,6 +61,7 @@ static char *create_stmts[] = {
"imsi NUMERIC UNIQUE NOT NULL, "
"name TEXT, "
"extension TEXT UNIQUE, "
+ "external_number TEXT, "
"authorized INTEGER NOT NULL DEFAULT 0, "
"tmsi TEXT UNIQUE, "
"lac INTEGER NOT NULL DEFAULT 0, "
@@ -634,6 +635,10 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result)
if (string)
strncpy(subscr->extension, string, GSM_EXTENSION_LENGTH);
+ string = dbi_result_get_string(result, "external_number");
+ if (string)
+ strncpy(subscr->external_number, string, GSM_EXTENSION_LENGTH);
+
subscr->lac = dbi_result_get_uint(result, "lac");
if (!dbi_result_field_is_null(result, "expire_lu"))
@@ -676,8 +681,8 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
dbi_conn_quote_string_copy(conn, id, &quoted);
result = dbi_conn_queryf(conn,
BASE_QUERY
- "WHERE extension = %s ",
- quoted
+ "WHERE extension = %s OR external_number = %s ",
+ quoted, quoted
);
free(quoted);
break;
@@ -708,8 +713,9 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
subscr->id = dbi_result_get_ulonglong(result, "id");
db_set_from_query(subscr, result);
- DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
- subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
+ DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', EXTERN '%s', LAC %hu, AUTH %u\n",
+ subscr->id, subscr->imsi, subscr->name, subscr->tmsi,
+ subscr->extension, subscr->external_number,
subscr->lac, subscr->authorized);
dbi_result_free(result);
@@ -751,12 +757,14 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
{
dbi_result result;
char tmsi[14];
- char *q_tmsi, *q_name, *q_extension;
+ char *q_tmsi, *q_name, *q_extension, *q_external_number;
dbi_conn_quote_string_copy(conn,
subscriber->name, &q_name);
dbi_conn_quote_string_copy(conn,
subscriber->extension, &q_extension);
+ dbi_conn_quote_string_copy(conn,
+ subscriber->external_number, &q_external_number);
if (subscriber->tmsi != GSM_RESERVED_TMSI) {
sprintf(tmsi, "%u", subscriber->tmsi);
@@ -772,6 +780,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
"SET updated = datetime('now'), "
"name = %s, "
"extension = %s, "
+ "external_number = %s, "
"authorized = %i, "
"tmsi = %s, "
"lac = %i, "
@@ -779,6 +788,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
"WHERE imsi = %s ",
q_name,
q_extension,
+ q_external_number,
subscriber->authorized,
q_tmsi,
subscriber->lac,
@@ -789,6 +799,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
"SET updated = datetime('now'), "
"name = %s, "
"extension = %s, "
+ "external_number = %s, "
"authorized = %i, "
"tmsi = %s, "
"lac = %i, "
@@ -796,6 +807,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
"WHERE imsi = %s ",
q_name,
q_extension,
+ q_external_number,
subscriber->authorized,
q_tmsi,
subscriber->lac,
@@ -806,6 +818,7 @@ int db_sync_subscriber(struct gsm_subscriber *subscriber)
free(q_tmsi);
free(q_name);
free(q_extension);
+ free(q_external_number);
if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to update Subscriber (by IMSI).\n");
@@ -957,6 +970,16 @@ int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber)
DEBUGP(DDB, "Allocated extension %i for IMSI %s.\n", try, subscriber->imsi);
return db_sync_subscriber(subscriber);
}
+
+int db_subscriber_assoc_extern_number(struct gsm_subscriber *subscriber, char *extern_number)
+{
+ strncpy(subscriber->external_number, extern_number,
+ sizeof(subscriber->external_number)-1);
+ DEBUGP(DDB, "Associated external number '%s' for "GSM_SUBS_FMT_STR".\n",
+ subscriber->external_number, GSM_SUBS_FMT_VAL(subscriber));
+ return db_sync_subscriber(subscriber);
+}
+
/*
* try to allocate a new unique token for this subscriber and return it
* via a parameter. if the subscriber already has a token, return
diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c
index 5ace8f666..594a72b3a 100644
--- a/openbsc/src/libmsc/gsm_subscriber.c
+++ b/openbsc/src/libmsc/gsm_subscriber.c
@@ -302,7 +302,8 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
struct gsm_subscriber *subscr;
llist_for_each_entry(subscr, subscr_bsc_active_subscribers(), entry) {
- if (strcmp(subscr->extension, ext) == 0)
+ if (strcmp(subscr->extension, ext) == 0
+ || strcmp(subscr->external_number, ext) == 0)
return subscr_get(subscr);
}
diff --git a/openbsc/src/libmsc/sip_sms.c b/openbsc/src/libmsc/sip_sms.c
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/openbsc/src/libmsc/sip_sms.c
@@ -0,0 +1 @@
+
diff --git a/openbsc/src/libmsc/smpp_openbsc.c b/openbsc/src/libmsc/smpp_openbsc.c
index 8e0085d0c..dc6bf8d91 100644
--- a/openbsc/src/libmsc/smpp_openbsc.c
+++ b/openbsc/src/libmsc/smpp_openbsc.c
@@ -446,7 +446,7 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
deliver.source_addr_npi = NPI_ISDN_E163_E164;
snprintf((char *)deliver.source_addr,
sizeof(deliver.source_addr), "%s",
- sms->sender->extension);
+ strlen(sms->sender->external_number)?sms->sender->external_number:sms->sender->extension);
}
deliver.dest_addr_ton = sms->dst.ton;
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index 5ef449790..4daa3c6c5 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -65,6 +65,9 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
if (subscr->extension)
vty_out(vty, " Extension: %s%s", subscr->extension,
VTY_NEWLINE);
+ if (strlen(subscr->external_number))
+ vty_out(vty, " External number: %s%s", subscr->external_number,
+ VTY_NEWLINE);
vty_out(vty, " LAC: %d/0x%x%s",
subscr->lac, subscr->lac, VTY_NEWLINE);
vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c
index c3beee22f..7cf656196 100644
--- a/openbsc/tests/db/db_test.c
+++ b/openbsc/tests/db/db_test.c
@@ -26,39 +26,55 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <inttypes.h>
static struct gsm_network dummy_net;
#define SUBSCR_PUT(sub) \
- sub->net = &dummy_net; \
- subscr_put(sub);
+ if (sub) { \
+ sub->net = &dummy_net; \
+ subscr_put(sub); \
+ }
#define COMPARE(original, copy) \
- if (original->id != copy->id) \
- printf("Ids do not match in %s:%d %llu %llu\n", \
- __FUNCTION__, __LINE__, original->id, copy->id); \
- if (original->lac != copy->lac) \
- printf("LAC do not match in %s:%d %d %d\n", \
- __FUNCTION__, __LINE__, original->lac, copy->lac); \
- if (original->authorized != copy->authorized) \
- printf("Authorize do not match in %s:%d %d %d\n", \
- __FUNCTION__, __LINE__, original->authorized, \
- copy->authorized); \
- if (strcmp(original->imsi, copy->imsi) != 0) \
- printf("IMSIs do not match in %s:%d '%s' '%s'\n", \
- __FUNCTION__, __LINE__, original->imsi, copy->imsi); \
- if (original->tmsi != copy->tmsi) \
- printf("TMSIs do not match in %s:%d '%u' '%u'\n", \
- __FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \
- if (strcmp(original->name, copy->name) != 0) \
- printf("names do not match in %s:%d '%s' '%s'\n", \
- __FUNCTION__, __LINE__, original->name, copy->name); \
- if (strcmp(original->extension, copy->extension) != 0) \
- printf("Extensions do not match in %s:%d '%s' '%s'\n", \
- __FUNCTION__, __LINE__, original->extension, copy->extension); \
+ if (!original) \
+ printf("NULL original in %s:%d\n", \
+ __FUNCTION__, __LINE__); \
+ if (!copy) \
+ printf("NULL copy in %s:%d\n", \
+ __FUNCTION__, __LINE__); \
+ if (original && copy) { \
+ if (original->id != copy->id) \
+ printf("Ids do not match in %s:%d %llu %llu\n", \
+ __FUNCTION__, __LINE__, original->id, copy->id); \
+ if (original->lac != copy->lac) \
+ printf("LAC do not match in %s:%d %d %d\n", \
+ __FUNCTION__, __LINE__, original->lac, copy->lac); \
+ if (original->authorized != copy->authorized) \
+ printf("Authorize do not match in %s:%d %d %d\n", \
+ __FUNCTION__, __LINE__, original->authorized, \
+ copy->authorized); \
+ if (strcmp(original->imsi, copy->imsi) != 0) \
+ printf("IMSIs do not match in %s:%d '%s' '%s'\n", \
+ __FUNCTION__, __LINE__, original->imsi, copy->imsi); \
+ if (original->tmsi != copy->tmsi) \
+ printf("TMSIs do not match in %s:%d '%u' '%u'\n", \
+ __FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \
+ if (strcmp(original->name, copy->name) != 0) \
+ printf("names do not match in %s:%d '%s' '%s'\n", \
+ __FUNCTION__, __LINE__, original->name, copy->name); \
+ if (strcmp(original->extension, copy->extension) != 0) \
+ printf("Extensions do not match in %s:%d '%s' '%s'\n", \
+ __FUNCTION__, __LINE__, original->extension, copy->extension); \
+ if (strcmp(original->external_number, copy->external_number) != 0) \
+ printf("External numbers do not match in %s:%d '%s' '%s'\n", \
+ __FUNCTION__, __LINE__, original->external_number, copy->external_number); \
+ }
int main()
{
+ char scratch_str[256];
+
printf("Testing subscriber database code.\n");
osmo_init_logging(&log_info);
@@ -89,12 +105,32 @@ int main()
alice = db_create_subscriber(NULL, alice_imsi);
db_subscriber_assoc_imei(alice, "1234567890");
db_subscriber_alloc_tmsi(alice);
+ db_subscriber_assoc_extern_number(alice, "123456789012345");
alice->lac=42;
db_sync_subscriber(alice);
+ /* Get by TMSI */
+ snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi);
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_TMSI, scratch_str);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* Get by IMSI */
alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi);
COMPARE(alice, alice_db);
- SUBSCR_PUT(alice);
SUBSCR_PUT(alice_db);
+ /* Get by id */
+ snprintf(scratch_str, sizeof(scratch_str), "%llu", alice->id);
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_ID, scratch_str);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* Get by extension */
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, alice->extension);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* And now by the external number alias */
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, "123456789012345");
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ SUBSCR_PUT(alice);
alice_imsi = "9993245423445";
alice = db_create_subscriber(NULL, alice_imsi);
@@ -103,10 +139,31 @@ int main()
db_sync_subscriber(alice);
db_subscriber_assoc_imei(alice, "1234567890");
db_subscriber_assoc_imei(alice, "6543560920");
+ /* This number is too long and should be truncated. */
+ db_subscriber_assoc_extern_number(alice, "2345678901234567890");
+ /* Get by TMSI */
+ snprintf(scratch_str, sizeof(scratch_str), "%"PRIu32, alice->tmsi);
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_TMSI, scratch_str);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* Get by IMSI */
alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_IMSI, alice_imsi);
COMPARE(alice, alice_db);
- SUBSCR_PUT(alice);
SUBSCR_PUT(alice_db);
+ /* Get by id */
+ snprintf(scratch_str, sizeof(scratch_str), "%llu", alice->id);
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_ID, scratch_str);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* Get by extension */
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, alice->extension);
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ /* And now by the external number alias */
+ alice_db = db_get_subscriber(NULL, GSM_SUBSCRIBER_EXTENSION, "234567890123456");
+ COMPARE(alice, alice_db);
+ SUBSCR_PUT(alice_db);
+ SUBSCR_PUT(alice);
db_fini();