summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/host/layer23/include/osmocom/bb/common/osmocom_data.h4
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/db.h6
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/db_sms.h16
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/subscriber.h1
-rw-r--r--src/host/layer23/src/mobile/Makefile.am15
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c58
-rw-r--r--src/host/layer23/src/mobile/db.c88
-rw-r--r--src/host/layer23/src/mobile/db_sms.c191
-rw-r--r--src/host/layer23/src/mobile/gsm411_sms.c6
9 files changed, 382 insertions, 3 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
index 17dad10d..a88a12db 100644
--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -1,6 +1,8 @@
#ifndef osmocom_data_h
#define osmocom_data_h
+#include <sqlite3.h>
+
#include <osmocom/core/select.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/write_queue.h>
@@ -77,6 +79,8 @@ struct osmocom_ms {
struct gsm48_cclayer cclayer;
struct osmomncc_entity mncc_entity;
struct llist_head trans_list;
+
+ sqlite3 *db_sms;
};
enum osmobb_sig_subsys {
diff --git a/src/host/layer23/include/osmocom/bb/mobile/db.h b/src/host/layer23/include/osmocom/bb/mobile/db.h
new file mode 100644
index 00000000..00b37ff4
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/db.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <sqlite3.h>
+
+int db_open(sqlite3 **db, const char *db_name);
+void db_close(sqlite3 *db);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/db_sms.h b/src/host/layer23/include/osmocom/bb/mobile/db_sms.h
new file mode 100644
index 00000000..199207e5
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/mobile/db_sms.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <sqlite3.h>
+#include <stdint.h>
+
+struct db_sms_record {
+ char *dst_number;
+ char *src_imsi;
+ char *text;
+ int row_id;
+};
+
+int db_prepare(sqlite3 *db);
+int db_pop_sms(sqlite3 *db, struct db_sms_record **sms);
+int db_push_sms(sqlite3 *db, char *dst_imsi, uint32_t dst_tmsi,
+ char *src_number, char *text);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
index cd821e66..73ef8cf4 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/subscriber.h
@@ -118,6 +118,7 @@ char *gsm_check_imsi(const char *imsi);
int gsm_subscr_get_key_seq(struct osmocom_ms *ms, struct gsm_subscriber *subscr);
int multi_imsi_work(struct osmocom_ms *ms);
int multi_imsi_spoof(struct osmocom_ms *ms, struct gsm_subscriber_creds *src);
+int multi_imsi_switch_imsi(struct osmocom_ms *ms, const char *imsi);
#endif /* _SUBSCRIBER_H */
diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am
index 04dd0257..a276076e 100644
--- a/src/host/layer23/src/mobile/Makefile.am
+++ b/src/host/layer23/src/mobile/Makefile.am
@@ -1,11 +1,20 @@
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBGPS_CFLAGS)
-LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBGPS_LIBS)
+LDADD = \
+ ../common/liblayer23.a \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOVTY_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
+ $(LIBOSMOCODEC_LIBS) \
+ $(LIBGPS_LIBS) \
+ -lsqlite3
noinst_LIBRARIES = libmobile.a
-libmobile_a_SOURCES = gsm322.c gsm480_ss.c gsm411_sms.c gsm48_cc.c gsm48_mm.c \
+libmobile_a_SOURCES = \
+ gsm322.c gsm480_ss.c gsm411_sms.c gsm48_cc.c gsm48_mm.c \
gsm48_rr.c mnccms.c settings.c subscriber.c support.c \
- transaction.c vty_interface.c voice.c mncc_sock.c
+ transaction.c vty_interface.c voice.c mncc_sock.c \
+ db.c db_sms.c
bin_PROGRAMS = mobile
diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c
index 7198f939..28ac3301 100644
--- a/src/host/layer23/src/mobile/app_mobile.c
+++ b/src/host/layer23/src/mobile/app_mobile.c
@@ -37,6 +37,8 @@
#include <osmocom/bb/mobile/app_mobile.h>
#include <osmocom/bb/mobile/mncc.h>
#include <osmocom/bb/mobile/voice.h>
+#include <osmocom/bb/mobile/db.h>
+#include <osmocom/bb/mobile/db_sms.h>
#include <osmocom/bb/common/sap_interface.h>
#include <osmocom/vty/telnet_interface.h>
@@ -56,6 +58,38 @@ int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg);
int (*mncc_recv_app)(struct osmocom_ms *ms, int, void *);
static int quit;
+static int db_sms_check(struct osmocom_ms *ms)
+{
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm_settings *set = &ms->settings;
+ struct db_sms_record *sms = NULL;
+ const char *sms_sca = "99999";
+ int rc;
+
+ // Phone should be registered and should support SMS
+ if (cs->state != GSM322_C3_CAMPED_NORMALLY || !set->sms_ptp)
+ return 0;
+
+ // Check if we have a new message to send
+ rc = db_pop_sms(ms->db_sms, &sms);
+ if (rc || !sms)
+ return 0;
+
+ // So, we got a new SMS to send
+ vty_notify(ms, "Got a new SMS to send:\n");
+ vty_notify(ms, "IMSI (%s) -> extension (%s)\n",
+ sms->src_imsi, sms->dst_number);
+
+ // Set up required IMSI
+ multi_imsi_switch_imsi(ms, sms->src_imsi);
+
+ // Send SMS
+ sms_send(ms, sms_sca, sms->dst_number, sms->text);
+
+ talloc_free(sms);
+ return 0;
+}
+
/* handle ms instance */
int mobile_work(struct osmocom_ms *ms)
{
@@ -73,6 +107,7 @@ int mobile_work(struct osmocom_ms *ms)
w |= gsm_sim_job_dequeue(ms);
w |= mncc_dequeue(ms);
w |= multi_imsi_work(ms);
+ w |= db_sms_check(ms);
if (w)
work = 1;
} while (w);
@@ -166,6 +201,7 @@ int mobile_exit(struct osmocom_ms *ms, int force)
gsm411_sms_exit(ms);
gsm_sim_exit(ms);
lapdm_channel_exit(&ms->lapdm_channel);
+ db_close(ms->db_sms);
if (ms->started) {
ms->shutdown = 2; /* being down, wait for reset */
@@ -183,6 +219,7 @@ int mobile_exit(struct osmocom_ms *ms, int force)
/* power-on ms instance */
int mobile_init(struct osmocom_ms *ms)
{
+ char *db_name;
int rc;
gsm_settings_arfcn(ms);
@@ -196,6 +233,27 @@ int mobile_init(struct osmocom_ms *ms)
ms->lapdm_channel.lapdm_acch.datalink[DL_SAPI3].dl.t200_usec = 0;
lapdm_channel_set_l1(&ms->lapdm_channel, l1ctl_ph_prim_cb, ms);
+ // Compose database name
+ db_name = talloc_asprintf(ms, "sms_db_%s.sqlite3", ms->name);
+
+ // Init database connection
+ rc = db_open(&ms->db_sms, db_name);
+ if (rc) {
+ ms->l2_wq.bfd.fd = -1;
+ mobile_exit(ms, 1);
+ return rc;
+ }
+
+ // Prepare database if required
+ rc = db_prepare(ms->db_sms);
+ if (rc) {
+ ms->l2_wq.bfd.fd = -1;
+ mobile_exit(ms, 1);
+ return rc;
+ }
+
+ talloc_free(db_name);
+
/* init SAP client before SIM card starts up */
osmosap_init(ms);
diff --git a/src/host/layer23/src/mobile/db.c b/src/host/layer23/src/mobile/db.c
new file mode 100644
index 00000000..f22d5049
--- /dev/null
+++ b/src/host/layer23/src/mobile/db.c
@@ -0,0 +1,88 @@
+/*
+ * (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <talloc.h>
+#include <string.h>
+#include <sqlite3.h>
+
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/mobile/db.h>
+
+extern void *l23_ctx;
+
+static char *db_compose_path(const char *db_name)
+{
+ const char *db_home_path = ".osmocom/bb";
+ const char *db_tmp_path = "/tmp";
+ char const *home = getenv("HOME");
+ char *db_full_path;
+ size_t len;
+
+ if (home != NULL) {
+ len = strlen(home) + strlen(db_home_path) + strlen(db_name) + 3;
+ db_full_path = talloc_size(l23_ctx, len);
+ if (db_full_path != NULL)
+ snprintf(db_full_path, len, "%s/%s/%s",
+ home, db_home_path, db_name);
+ } else {
+ len = strlen(db_tmp_path) + strlen(db_name) + 2;
+ db_full_path = talloc_size(l23_ctx, len);
+ if (db_full_path != NULL)
+ snprintf(db_full_path, len, "%s/%s",
+ db_tmp_path, db_name);
+ }
+
+ return db_full_path;
+}
+
+int db_open(sqlite3 **db, const char *db_name)
+{
+ char *db_full_path;
+ int rc;
+
+ // Compose full database path
+ db_full_path = db_compose_path(db_name);
+ if (db_full_path == NULL)
+ return -ENOMEM;
+
+ // Connect to database
+ rc = sqlite3_open(db_full_path, db);
+ if (rc) {
+ fprintf(stderr, "[!] Couldn't open database: %s\n",
+ sqlite3_errmsg(*db));
+ goto final;
+ }
+
+ fprintf(stderr, "[i] Successfully connected to database\n");
+
+final:
+ talloc_free(db_full_path);
+
+ return rc;
+}
+
+void db_close(sqlite3 *db)
+{
+ if (!db)
+ sqlite3_close(db);
+}
diff --git a/src/host/layer23/src/mobile/db_sms.c b/src/host/layer23/src/mobile/db_sms.c
new file mode 100644
index 00000000..fbca2773
--- /dev/null
+++ b/src/host/layer23/src/mobile/db_sms.c
@@ -0,0 +1,191 @@
+/*
+ * (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <talloc.h>
+#include <string.h>
+#include <stdint.h>
+#include <sqlite3.h>
+
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/mobile/db.h>
+#include <osmocom/bb/mobile/db_sms.h>
+
+extern void *l23_ctx;
+
+int db_prepare(sqlite3 *db)
+{
+ char *err = 0;
+ int rc = 0;
+
+ const char *inbox_sql = \
+ "CREATE TABLE IF NOT EXISTS inbox (" \
+ "dst_imsi TEXT NOT NULL, " \
+ "dst_tmsi TEXT NOT NULL, " \
+ "src_number TEXT NOT NULL, " \
+ "date DATETIME DEFAULT CURRENT_TIMESTAMP, " \
+ "handled INT DEFAULT 0, " \
+ "text TEXT NOT NULL" \
+ ");";
+
+ const char *outbox_sql = \
+ "CREATE TABLE IF NOT EXISTS outbox (" \
+ "src_imsi text TEXT NOT NULL, " \
+ "dst_number text TEXT NOT NULL, " \
+ "date DATETIME DEFAULT CURRENT_TIMESTAMP, " \
+ "handled INT DEFAULT 0, " \
+ "text TEXT NOT NULL" \
+ ");";
+
+ rc = sqlite3_exec(db, inbox_sql, NULL, 0, &err);
+ if (rc != SQLITE_DONE && rc != SQLITE_OK) {
+ fprintf(stderr, "[!] Couldn't init database: %s\n", err);
+ return rc;
+ }
+
+ rc = sqlite3_exec(db, outbox_sql, NULL, 0, &err) == SQLITE_DONE;
+ if (rc != SQLITE_DONE && rc != SQLITE_OK) {
+ fprintf(stderr, "[!] Couldn't init database: %s\n", err);
+ return rc;
+ }
+
+ fprintf(stderr, "[i] Database init complete\n");
+
+ return 0;
+}
+
+int db_push_sms(sqlite3 *db, char *dst_imsi, uint32_t dst_tmsi,
+ char *src_number, char *text)
+{
+ sqlite3_stmt *stmt;
+ char *tmsi_str;
+ int rc;
+
+ const char *push_sql = \
+ "INSERT INTO inbox " \
+ "(dst_imsi, dst_tmsi, src_number, text) "
+ "VALUES (?, ?, ?, ?);";
+
+ rc = sqlite3_prepare(db, push_sql, strlen(push_sql), &stmt, NULL);
+ if (rc != SQLITE_OK) {
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+ return rc;
+ }
+
+ // Convert TMSI to string
+ tmsi_str = talloc_asprintf(l23_ctx, "0x%08x", dst_tmsi);
+
+ // Bind query params
+ sqlite3_bind_text(stmt, 1, dst_imsi, strlen(dst_imsi), 0);
+ sqlite3_bind_text(stmt, 2, tmsi_str, strlen(tmsi_str), 0);
+ sqlite3_bind_text(stmt, 3, src_number, strlen(src_number), 0);
+ sqlite3_bind_text(stmt, 4, text, strlen(text), 0);
+
+ // Commit
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE && rc != SQLITE_OK) {
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+ return rc;
+ }
+
+ printf("[i] Message saved\n");
+
+ sqlite3_finalize(stmt);
+ talloc_free(tmsi_str);
+
+ return 0;
+}
+
+int db_pop_sms(sqlite3 *db, struct db_sms_record **sms)
+{
+ struct db_sms_record *sms_new = NULL;
+ sqlite3_stmt *stmt;
+ int rc;
+
+ const char *pop_select_sql = \
+ "SELECT rowid, src_imsi, dst_number, text " \
+ "FROM outbox WHERE handled = 0;";
+
+ const char *pop_update_sql = \
+ "UPDATE outbox SET handled = 1 " \
+ "WHERE rowid = ?;";
+
+ // Prepare query
+ rc = sqlite3_prepare(db, pop_select_sql, strlen(pop_select_sql),
+ &stmt, NULL);
+ if (rc != SQLITE_OK) {
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+ return rc;
+ }
+
+ // Attempt to get a record
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_ROW) {
+ if (rc != SQLITE_DONE && rc != SQLITE_OK)
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+
+ goto final;
+ }
+
+ // Allocate a new structure for SMS
+ sms_new = talloc(l23_ctx, struct db_sms_record);
+ if (sms_new == NULL) {
+ rc = -ENOMEM;
+ goto final;
+ }
+
+ // Fill structure
+ sms_new->row_id = sqlite3_column_int(stmt, 0);
+ sms_new->src_imsi = talloc_strdup(sms_new,
+ (char *) sqlite3_column_text(stmt, 1));
+ sms_new->dst_number = talloc_strdup(sms_new,
+ (char *) sqlite3_column_text(stmt, 2));
+ sms_new->text = talloc_strdup(sms_new,
+ (char *) sqlite3_column_text(stmt, 3));
+
+ // Set external pointer
+ *sms = sms_new;
+
+ // Prepare another query
+ sqlite3_finalize(stmt);
+ rc = sqlite3_prepare(db, pop_update_sql, strlen(pop_update_sql),
+ &stmt, NULL);
+ if (rc != SQLITE_OK) {
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+ return rc;
+ }
+
+ // Mark this record as 'handled'
+ sqlite3_bind_int(stmt, 1, sms_new->row_id);
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE && rc != SQLITE_OK) {
+ fprintf(stderr, "[!] SQLite error: %s\n", sqlite3_errmsg(db));
+ goto final;
+ }
+
+ printf("[i] Got a new message from DB\n");
+
+final:
+ sqlite3_finalize(stmt);
+
+ return (rc != SQLITE_DONE && rc != SQLITE_OK) ? rc : 0;
+}
diff --git a/src/host/layer23/src/mobile/gsm411_sms.c b/src/host/layer23/src/mobile/gsm411_sms.c
index 655fe535..85449bfa 100644
--- a/src/host/layer23/src/mobile/gsm411_sms.c
+++ b/src/host/layer23/src/mobile/gsm411_sms.c
@@ -37,6 +37,8 @@
#include <osmocom/bb/mobile/mncc.h>
#include <osmocom/bb/mobile/transaction.h>
#include <osmocom/bb/mobile/gsm411_sms.h>
+#include <osmocom/bb/mobile/db.h>
+#include <osmocom/bb/mobile/db_sms.h>
#include <osmocom/gsm/gsm0411_utils.h>
#include <osmocom/core/talloc.h>
#include <osmocom/bb/mobile/vty.h>
@@ -213,6 +215,10 @@ fail:
fprintf(fp, "[SMS from %s]\n%s\n", gsms->address, gsms->text);
fclose(fp);
+ // Save SMS to database
+ db_push_sms(ms->db_sms, ms->subscr.imsi, ms->subscr.tmsi,
+ gsms->address, gsms->text);
+
talloc_free(sms_file);
return 0;