summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/host/layer23/include/osmocom/bb/common/osmocom_data.h8
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm322.h2
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h1
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/settings.h3
-rw-r--r--src/host/layer23/src/common/l1l2_interface.c1
-rw-r--r--src/host/layer23/src/mobile/Makefile.am2
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c100
-rw-r--r--src/host/layer23/src/mobile/gsm322.c12
-rw-r--r--src/host/layer23/src/mobile/gsm48_mm.c15
-rw-r--r--src/host/layer23/src/mobile/main.c325
-rw-r--r--src/host/layer23/src/mobile/settings.c12
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c271
12 files changed, 646 insertions, 106 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 77a60672..da35cdb0 100644
--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -53,6 +53,7 @@ struct osmocom_ms {
struct write_queue l2_wq, sap_wq;
uint16_t test_arfcn;
+ uint8_t delete, shutdown, started;
struct gsm_support support;
struct gsm_settings settings;
struct gsm_subscriber subscr;
@@ -70,9 +71,10 @@ struct osmocom_ms {
enum osmobb_sig_subsys {
SS_L1CTL,
+ SS_GLOBAL,
};
-enum osmobb_meas_sig {
+enum osmobb_l1ctl_sig {
S_L1CTL_FBSB_ERR,
S_L1CTL_FBSB_RESP,
S_L1CTL_RESET,
@@ -83,6 +85,10 @@ enum osmobb_meas_sig {
S_L1CTL_LOSS_IND,
};
+enum osmobb_global_sig {
+ S_GLOBAL_SHUTDOWN,
+};
+
struct osmobb_fbsb_res {
struct osmocom_ms *ms;
int8_t snr;
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm322.h b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
index 78e380fe..467ff39a 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
@@ -196,6 +196,8 @@ void start_loss_timer(struct gsm322_cellsel *cs, int sec, int micro);
extern const char *plmn_a_state_names[];
extern const char *plmn_m_state_names[];
extern const char *cs_state_names[];
+int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
char *gsm_print_rxlev(uint8_t rxlev);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
index 0d181824..447dc95f 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
@@ -191,7 +191,6 @@ struct gsm48_mmlayer {
/* other */
uint8_t est_cause; /* cause of establishment msg */
int mr_substate; /* rem most recent substate */
- uint8_t power_off; /* set, if power off after detach */
uint8_t power_off_idle; /* waits for IDLE before po */
};
diff --git a/src/host/layer23/include/osmocom/bb/mobile/settings.h b/src/host/layer23/include/osmocom/bb/mobile/settings.h
index 178ef081..d0848a82 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/settings.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/settings.h
@@ -8,6 +8,9 @@ enum {
};
struct gsm_settings {
+ char layer2_socket_path[128];
+ char sap_socket_path[128];
+
/* IMEI */
char imei[16];
char imeisv[17];
diff --git a/src/host/layer23/src/common/l1l2_interface.c b/src/host/layer23/src/common/l1l2_interface.c
index 28356daa..9d31532b 100644
--- a/src/host/layer23/src/common/l1l2_interface.c
+++ b/src/host/layer23/src/common/l1l2_interface.c
@@ -131,6 +131,7 @@ int layer2_open(struct osmocom_ms *ms, const char *socket_path)
rc = bsc_register_fd(&ms->l2_wq.bfd);
if (rc != 0) {
fprintf(stderr, "Failed to register fd.\n");
+ close(ms->l2_wq.bfd.fd);
return rc;
}
diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am
index bd98bafd..12f0f76b 100644
--- a/src/host/layer23/src/mobile/Makefile.am
+++ b/src/host/layer23/src/mobile/Makefile.am
@@ -9,7 +9,7 @@ libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \
bin_PROGRAMS = mobile
-mobile_SOURCES = ../common/main.c app_mobile.c
+mobile_SOURCES = main.c app_mobile.c
mobile_LDADD = libmobile.a $(LDADD)
diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c
index 6abb8703..293d1355 100644
--- a/src/host/layer23/src/mobile/app_mobile.c
+++ b/src/host/layer23/src/mobile/app_mobile.c
@@ -24,14 +24,12 @@
#include <errno.h>
#include <signal.h>
-#include <time.h>
#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1l2_interface.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/common/lapdm.h>
#include <osmocom/bb/common/logging.h>
-#include <osmocom/bb/common/gps.h>
#include <osmocom/bb/mobile/gsm48_rr.h>
#include <osmocom/bb/mobile/vty.h>
#include <osmocom/vty/telnet_interface.h>
@@ -39,18 +37,10 @@
#include <osmocore/msgb.h>
#include <osmocore/talloc.h>
#include <osmocore/select.h>
-#include <osmocore/signal.h>
-
-extern struct log_target *stderr_target;
-static const char *config_file = "/etc/osmocom/osmocom.cfg";
-extern void *l23_ctx;
-extern unsigned short vty_port;
-extern int vty_reading;
-
-int mobile_started = 0;
int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg);
int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg);
+extern int (*l23_app_exit) (struct osmocom_ms *ms, int force);
int mobile_work(struct osmocom_ms *ms)
{
@@ -73,7 +63,7 @@ int mobile_work(struct osmocom_ms *ms)
return work;
}
-static int signal_cb(unsigned int subsys, unsigned int signal,
+int mobile_signal_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct osmocom_ms *ms;
@@ -85,12 +75,12 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_L1CTL_RESET:
- if (mobile_started)
- break;
-
ms = signal_data;
set = &ms->settings;
+ if (ms->started)
+ break;
+
/* insert test card, if enabled */
switch (set->sim_type) {
case GSM_SIM_TYPE_READER:
@@ -113,19 +103,19 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
gsm322_cs_sendmsg(ms, nmsg);
}
- mobile_started = 1;
+ ms->started = 1;
}
return 0;
}
-int mobile_exit(struct osmocom_ms *ms)
+int mobile_exit(struct osmocom_ms *ms, int force)
{
struct gsm48_mmlayer *mm = &ms->mmlayer;
- if (!mm->power_off && mobile_started) {
+ if (!force && ms->started) {
struct msgb *nmsg;
- mm->power_off = 1;
+ ms->shutdown = 1; /* going down */
nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_IMSI_DETACH);
if (!nmsg)
return -ENOMEM;
@@ -134,48 +124,30 @@ int mobile_exit(struct osmocom_ms *ms)
return -EBUSY;
}
- /* in case there is a lockup during exit */
- signal(SIGINT, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGPIPE, SIG_DFL);
-
- unregister_signal_handler(SS_L1CTL, &signal_cb, NULL);
- gps_close();
gsm322_exit(ms);
gsm48_mm_exit(ms);
gsm48_rr_exit(ms);
gsm_subscr_exit(ms);
gsm48_cc_exit(ms);
gsm_sim_exit(ms);
- gsm_settings_exit(ms);
+ lapdm_exit(&ms->l2_entity.lapdm_acch);
+ lapdm_exit(&ms->l2_entity.lapdm_dcch);
- printf("Power off!\n");
+ ms->shutdown = 2; /* being down */
+ vty_notify(ms, NULL);
+ vty_notify(ms, "Power off!\n");
+ printf("Power off! (MS %s)\n", ms->name);
return 0;
}
-static struct vty_app_info vty_info = {
- .name = "OsmocomBB",
- .version = PACKAGE_VERSION,
- .go_parent_cb = ms_vty_go_parent,
-};
-
int l23_app_init(struct osmocom_ms *ms)
{
int rc;
- struct telnet_connection dummy_conn;
-// log_parse_category_mask(stderr_target, "DL1C:DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
- log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
- log_set_log_level(stderr_target, LOGL_INFO);
-
- srand(time(NULL));
-
- gps_init();
- gsm_support_init(ms);
+ lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
+ lapdm_init(&ms->l2_entity.lapdm_acch, ms);
gsm_sim_init(ms);
- gsm_settings_init(ms);
gsm48_cc_init(ms);
gsm_subscr_init(ms);
gsm48_rr_init(ms);
@@ -183,38 +155,36 @@ int l23_app_init(struct osmocom_ms *ms)
INIT_LLIST_HEAD(&ms->trans_list);
gsm322_init(ms);
- l23_app_work = mobile_work;
- register_signal_handler(SS_L1CTL, &signal_cb, NULL);
- l23_app_exit = mobile_exit;
-
- vty_init(&vty_info);
- ms_vty_init();
- dummy_conn.priv = NULL;
- vty_reading = 1;
- rc = vty_read_config_file(config_file, &dummy_conn);
+ rc = layer2_open(ms, ms->settings.layer2_socket_path);
if (rc < 0) {
- fprintf(stderr, "Failed to parse the config file: '%s'\n",
- config_file);
- fprintf(stderr, "Please check or create config file using: "
- "'touch %s'\n", config_file);
+ fprintf(stderr, "Failed during layer2_open()\n");
+ ms->l2_wq.bfd.fd = -1;
+ l23_app_exit(ms, 1);
return rc;
}
- vty_reading = 0;
- telnet_init(l23_ctx, NULL, vty_port);
- if (rc < 0)
+
+#if 0
+ rc = sap_open(ms, ms->settings.sap_socket_path);
+ if (rc < 0) {
+ fprintf(stderr, "Failed during sap_open(), no SIM reader\n");
+ ms->sap_wq.bfd.fd = -1;
+ l23_app_exit(ms, 1);
return rc;
+ }
+#endif
if (ms->settings.ch_cap == GSM_CAP_SDCCH)
ms->cclayer.mncc_recv = mncc_recv_dummy;
else
ms->cclayer.mncc_recv = mncc_recv_mobile;
- printf("VTY available on port %u.\n", vty_port);
-
gsm_random_imei(&ms->settings);
+ ms->shutdown = 0;
+ ms->started = 0;
+
l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
- printf("Mobile initialized, please start phone now!\n");
+ printf("Mobile '%s' initialized, please start phone now!\n", ms->name);
return 0;
}
diff --git a/src/host/layer23/src/mobile/gsm322.c b/src/host/layer23/src/mobile/gsm322.c
index 0b45f605..751b8b4b 100644
--- a/src/host/layer23/src/mobile/gsm322.c
+++ b/src/host/layer23/src/mobile/gsm322.c
@@ -33,12 +33,12 @@
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/l1ctl.h>
-#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/mobile/vty.h>
extern void *l23_ctx;
+extern int (*l23_app_exit) (struct osmocom_ms *ms, int force);
static void gsm322_cs_timeout(void *arg);
static void gsm322_cs_loss(void *arg);
@@ -2376,7 +2376,7 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
return l1ctl_tx_pm_req_range(ms, s, e);
}
-static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
+int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct osmocom_ms *ms;
@@ -2489,8 +2489,8 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
case S_L1CTL_RESET:
ms = signal_data;
if (ms->mmlayer.power_off_idle) {
- l23_app_exit(ms);
- exit(0);
+ l23_app_exit(ms, 1);
+ return 0;
}
break;
}
@@ -3525,8 +3525,6 @@ int gsm322_init(struct osmocom_ms *ms)
} else
LOGP(DCS, LOGL_INFO, "No stored BA list\n");
- register_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
-
return 0;
}
@@ -3545,8 +3543,6 @@ int gsm322_exit(struct osmocom_ms *ms)
LOGP(DPLMN, LOGL_INFO, "exit PLMN process\n");
LOGP(DCS, LOGL_INFO, "exit Cell Selection process\n");
- unregister_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
-
/* stop cell selection process (if any) */
new_c_state(cs, GSM322_C0_NULL);
diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c
index b77f4335..d4444cf2 100644
--- a/src/host/layer23/src/mobile/gsm48_mm.c
+++ b/src/host/layer23/src/mobile/gsm48_mm.c
@@ -33,12 +33,12 @@
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/common/l23_app.h>
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/mobile/gsm48_cc.h>
extern void *l23_ctx;
+extern int (*l23_app_exit) (struct osmocom_ms *ms, int force);
void mm_conn_free(struct gsm48_mm_conn *conn);
static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg);
@@ -1741,11 +1741,12 @@ static int gsm48_mm_imsi_detach_end(struct osmocom_ms *ms, struct msgb *msg)
subscr->sim_valid = 0;
/* wait for RR idle and then power off when IMSI is detached */
- if (mm->power_off) {
+ if (ms->shutdown) {
if (mm->state == GSM48_MM_ST_MM_IDLE) {
- l23_app_exit(ms);
- exit(0);
+ l23_app_exit(ms, 1);
+ return 0;
}
+ /* power off when MM idle */
mm->power_off_idle = 1;
return 0;
@@ -1816,9 +1817,9 @@ static int gsm48_mm_imsi_detach_release(struct osmocom_ms *ms, struct msgb *msg)
new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
/* power off */
- if (mm->power_off) {
- l23_app_exit(ms);
- exit(0);
+ if (ms->shutdown) {
+ l23_app_exit(ms, 1);
+ return 0;
}
return 0;
diff --git a/src/host/layer23/src/mobile/main.c b/src/host/layer23/src/mobile/main.c
new file mode 100644
index 00000000..9fd4ff78
--- /dev/null
+++ b/src/host/layer23/src/mobile/main.c
@@ -0,0 +1,325 @@
+/* Main method of the layer2/3 stack */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * 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 <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1l2_interface.h>
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/sap_interface.h>
+#include <osmocom/bb/misc/layer3.h>
+#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/gps.h>
+#include <osmocom/bb/mobile/vty.h>
+#include <osmocom/vty/telnet_interface.h>
+
+#include <osmocore/msgb.h>
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+#include <osmocore/linuxlist.h>
+#include <osmocore/gsmtap_util.h>
+#include <osmocore/signal.h>
+
+#include <arpa/inet.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+
+struct log_target *stderr_target;
+
+void *l23_ctx = NULL;
+static const char *config_file = "/etc/osmocom/osmocom.cfg";
+struct llist_head ms_list;
+static uint32_t gsmtap_ip = 0;
+unsigned short vty_port = 4247;
+int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
+int (*l23_app_exit) (struct osmocom_ms *ms, int force) = NULL;
+int quit = 0;
+
+int mobile_delete(struct osmocom_ms *ms, int force);
+int mobile_signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
+int mobile_work(struct osmocom_ms *ms);
+int mobile_exit(struct osmocom_ms *ms, int force);
+extern int vty_reading;
+
+
+const char *openbsc_copyright =
+ "Copyright (C) 2008-2010 ...\n"
+ "Contributions by ...\n\n"
+ "License GPLv2+: GNU GPL version 2 or later "
+ "<http://gnu.org/licenses/gpl.html>\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n";
+
+static void print_usage(const char *app)
+{
+ printf("Usage: %s\n", app);
+}
+
+static void print_help()
+{
+ printf(" Some help...\n");
+ printf(" -h --help this text\n");
+ printf(" -i --gsmtap-ip The destination IP used for GSMTAP.\n");
+ printf(" -v --vty-port The VTY port number to telnet to. "
+ "(default %u)\n", vty_port);
+ printf(" -d --debug Change debug flags.\n");
+}
+
+static void handle_options(int argc, char **argv)
+{
+ struct sockaddr_in gsmtap;
+ while (1) {
+ int option_index = 0, c;
+ static struct option long_options[] = {
+ {"help", 0, 0, 'h'},
+ {"gsmtap-ip", 1, 0, 'i'},
+ {"vty-port", 1, 0, 'v'},
+ {"debug", 1, 0, 'd'},
+ {0, 0, 0, 0},
+ };
+
+ c = getopt_long(argc, argv, "hi:v:d:",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage(argv[0]);
+ print_help();
+ exit(0);
+ break;
+ case 'i':
+ if (!inet_aton(optarg, &gsmtap.sin_addr)) {
+ perror("inet_aton");
+ exit(2);
+ }
+ gsmtap_ip = ntohl(gsmtap.sin_addr.s_addr);
+ break;
+ case 'v':
+ vty_port = atoi(optarg);
+ break;
+ case 'd':
+ log_parse_category_mask(stderr_target, optarg);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void sighandler(int sigset)
+{
+ if (sigset == SIGHUP || sigset == SIGPIPE)
+ return;
+
+ fprintf(stderr, "Signal %d recevied.\n", sigset);
+
+ /* in case there is a lockup during exit */
+ signal(SIGINT, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
+
+ dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+}
+
+int global_signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct osmocom_ms *ms, *ms2;
+
+ if (subsys != SS_GLOBAL)
+ return 0;
+
+ switch (signal) {
+ case S_GLOBAL_SHUTDOWN:
+ llist_for_each_entry_safe(ms, ms2, &ms_list, entity)
+ mobile_delete(ms, quit);
+
+ /* if second signal is received, force to exit */
+ quit = 1;
+ break;
+ }
+ return 0;
+}
+
+struct osmocom_ms *mobile_new(char *name)
+{
+ static struct osmocom_ms *ms;
+
+ ms = talloc_zero(l23_ctx, struct osmocom_ms);
+ if (!ms) {
+ fprintf(stderr, "Failed to allocate MS\n");
+ exit(1);
+ }
+ llist_add_tail(&ms->entity, &ms_list);
+
+ strcpy(ms->name, name);
+
+ ms->l2_wq.bfd.fd = -1;
+ ms->sap_wq.bfd.fd = -1;
+
+ gsm_support_init(ms);
+ gsm_settings_init(ms);
+
+ ms->shutdown = 2; /* being down */
+
+ return ms;
+}
+
+int mobile_delete(struct osmocom_ms *ms, int force)
+{
+ int rc;
+
+ ms->delete = 1;
+
+ if (ms->shutdown == 0 || (ms->shutdown == 1 && force)) {
+ rc = l23_app_exit(ms, force);
+ if (rc < 0)
+ return rc;
+ }
+
+ return 0;
+}
+
+static struct vty_app_info vty_info = {
+ .name = "OsmocomBB",
+ .version = PACKAGE_VERSION,
+ .go_parent_cb = ms_vty_go_parent,
+};
+
+int main(int argc, char **argv)
+{
+ struct osmocom_ms *ms, *ms2;
+ struct telnet_connection dummy_conn;
+ int rc;
+
+ printf("%s\n", openbsc_copyright);
+
+ srand(time(NULL));
+
+ INIT_LLIST_HEAD(&ms_list);
+ log_init(&log_info);
+ stderr_target = log_target_create_stderr();
+ log_add_target(stderr_target);
+ log_set_all_filter(stderr_target, 1);
+
+ l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
+
+ handle_options(argc, argv);
+
+// log_parse_category_mask(stderr_target, "DL1C:DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
+ log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
+ log_set_log_level(stderr_target, LOGL_INFO);
+
+ gps_init();
+
+ l23_app_work = mobile_work;
+ register_signal_handler(SS_GLOBAL, &global_signal_cb, NULL);
+ register_signal_handler(SS_L1CTL, &mobile_signal_cb, NULL);
+ register_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
+ l23_app_exit = mobile_exit;
+
+ vty_init(&vty_info);
+ ms_vty_init();
+ dummy_conn.priv = NULL;
+ vty_reading = 1;
+ rc = vty_read_config_file(config_file, &dummy_conn);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to parse the config file: '%s'\n",
+ config_file);
+ fprintf(stderr, "Please check or create config file using: "
+ "'touch %s'\n", config_file);
+ return rc;
+ }
+ vty_reading = 0;
+ telnet_init(l23_ctx, NULL, vty_port);
+ if (rc < 0)
+ return rc;
+ printf("VTY available on port %u.\n", vty_port);
+
+ if (llist_empty(&ms_list)) {
+ struct osmocom_ms *ms;
+
+ printf("No Mobile Station defined, creating: MS '1'\n");
+ ms = mobile_new("1");
+ if (ms)
+ l23_app_init(ms);
+ }
+
+ if (gsmtap_ip) {
+ rc = gsmtap_init(gsmtap_ip);
+ if (rc < 0) {
+ fprintf(stderr, "Failed during gsmtap_init()\n");
+ exit(1);
+ }
+ }
+
+ signal(SIGINT, sighandler);
+ signal(SIGHUP, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGPIPE, sighandler);
+
+ while (1) {
+ llist_for_each_entry_safe(ms, ms2, &ms_list, entity) {
+ if (ms->shutdown != 2)
+ l23_app_work(ms);
+ if (ms->shutdown == 2) {
+ if (ms->l2_wq.bfd.fd > -1) {
+ layer2_close(ms);
+ ms->l2_wq.bfd.fd = -1;
+ }
+
+ if (ms->sap_wq.bfd.fd > -1) {
+ sap_close(ms);
+ ms->sap_wq.bfd.fd = -1;
+ }
+
+ if (ms->delete) {
+ gsm_settings_exit(ms);
+ llist_del(&ms->entity);
+ talloc_free(ms);
+ }
+ }
+ }
+ if (quit && llist_empty(&ms_list))
+ break;
+ bsc_select_main(0);
+ }
+
+ unregister_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
+ unregister_signal_handler(SS_L1CTL, &mobile_signal_cb, NULL);
+ unregister_signal_handler(SS_GLOBAL, &global_signal_cb, NULL);
+
+ gps_close();
+
+ return 0;
+}
diff --git a/src/host/layer23/src/mobile/settings.c b/src/host/layer23/src/mobile/settings.c
index 6294ec65..89672a25 100644
--- a/src/host/layer23/src/mobile/settings.c
+++ b/src/host/layer23/src/mobile/settings.c
@@ -28,16 +28,26 @@
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/networks.h>
+static char *layer2_socket_path = "/tmp/osmocom_l2";
+static char *sap_socket_path = "/tmp/osmocom_sap";
+
int gsm_settings_init(struct osmocom_ms *ms)
{
struct gsm_settings *set = &ms->settings;
struct gsm_support *sup = &ms->support;
+ strcpy(set->layer2_socket_path, layer2_socket_path);
+ strcpy(set->sap_socket_path, sap_socket_path);
+
/* IMEI */
sprintf(set->imei, "000000000000000");
sprintf(set->imeisv, "0000000000000000");
- /* test sim */
+ /* SIM type */
+#warning TODO: Enable after SIM reader is available in master branch.
+// set->sim_type = SIM_TYPE_READER;
+
+ /* test SIM */
strcpy(set->test_imsi, "001010000000000");
set->test_rplmn_mcc = set->test_rplmn_mnc = 1;
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index c1d00f44..8a13a5dc 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -28,6 +28,7 @@
#include <osmocore/utils.h>
#include <osmocore/gsm48.h>
#include <osmocore/talloc.h>
+#include <osmocore/signal.h>
#include <osmocom/bb/common/osmocom_data.h>
#include <osmocom/bb/common/networks.h>
@@ -38,6 +39,10 @@
#include <osmocom/vty/telnet_interface.h>
void *l23_ctx;
+extern int l23_app_init(struct osmocom_ms *ms);
+extern int (*l23_app_exit) (struct osmocom_ms *ms, int force);
+extern struct osmocom_ms *mobile_new(char *name);
+extern int mobile_delete(struct osmocom_ms *ms, int force);
int mncc_call(struct osmocom_ms *ms, char *number);
int mncc_hangup(struct osmocom_ms *ms);
@@ -114,12 +119,14 @@ int vty_check_number(struct vty *vty, const char *number)
int vty_reading = 0;
-static void vty_restart(struct vty *vty)
+static void vty_restart(struct vty *vty, struct osmocom_ms *ms)
{
if (vty_reading)
return;
- vty_out(vty, "You must restart for change to take effect!%s",
- VTY_NEWLINE);
+ if (ms->shutdown != 0)
+ return;
+ vty_out(vty, "You must restart MS '%s' ('shutdown / no shutdown') for "
+ "change to take effect!%s", ms->name, VTY_NEWLINE);
}
static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
@@ -128,6 +135,10 @@ static struct osmocom_ms *get_ms(const char *name, struct vty *vty)
llist_for_each_entry(ms, &ms_list, entity) {
if (!strcmp(ms->name, name))
+ if (ms->shutdown) {
+ vty_out(vty, "MS '%s' is admin down.%s", name,
+ VTY_NEWLINE);
+ }
return ms;
}
vty_out(vty, "MS name '%s' does not exits.%s", name, VTY_NEWLINE);
@@ -224,8 +235,10 @@ DEFUN(show_states, show_states_cmd, "show states [ms_name]",
gsm_states_dump(ms, vty);
} else {
llist_for_each_entry(ms, &ms_list, entity) {
- gsm_states_dump(ms, vty);
- vty_out(vty, "%s", VTY_NEWLINE);
+ if (!ms->shutdown) {
+ gsm_states_dump(ms, vty);
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
}
}
@@ -245,8 +258,10 @@ DEFUN(show_subscr, show_subscr_cmd, "show subscriber [ms_name]",
gsm_subscr_dump(&ms->subscr, print_vty, vty);
} else {
llist_for_each_entry(ms, &ms_list, entity) {
- gsm_subscr_dump(&ms->subscr, print_vty, vty);
- vty_out(vty, "%s", VTY_NEWLINE);
+ if (!ms->shutdown) {
+ gsm_subscr_dump(&ms->subscr, print_vty, vty);
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
}
}
@@ -855,10 +870,29 @@ DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
"Select a mobile station to configure\nName of MS (see \"show ms\")")
{
struct osmocom_ms *ms;
+ int found = 0;
- ms = get_ms(argv[0], vty);
- if (!ms)
- return CMD_WARNING;
+ llist_for_each_entry(ms, &ms_list, entity) {
+ if (!strcmp(ms->name, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (!vty_reading) {
+ vty_out(vty, "MS name '%s' does not exits, try "
+ "'ms %s create'%s", argv[0], argv[0],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ ms = mobile_new((char *)argv[0]);
+ if (!ms) {
+ vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
vty->index = ms;
vty->node = MS_NODE;
@@ -866,6 +900,87 @@ DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME",
return CMD_SUCCESS;
}
+DEFUN(cfg_ms_create, cfg_ms_create_cmd, "ms MS_NAME create",
+ "Select a mobile station to configure\nName of MS (see \"show ms\")\n"
+ "Create if MS does not exists")
+{
+ struct osmocom_ms *ms;
+ int found = 0;
+
+ llist_for_each_entry(ms, &ms_list, entity) {
+ if (!strcmp(ms->name, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ ms = mobile_new((char *)argv[0]);
+ if (!ms) {
+ vty_out(vty, "Failed to add MS name '%s'%s", argv[0],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ vty->index = ms;
+ vty->node = MS_NODE;
+
+ vty_out(vty, "MS '%s' created, after configuration, do 'no shutdown'%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_rename, cfg_ms_rename_cmd, "ms MS_NAME rename MS_NAME",
+ "Select a mobile station to configure\nName of MS (see \"show ms\")\n"
+ "Rename MS\nNew name of MS")
+{
+ struct osmocom_ms *ms;
+ int found = 0;
+
+ llist_for_each_entry(ms, &ms_list, entity) {
+ if (!strcmp(ms->name, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ vty_out(vty, "MS name '%s' does not exist%s", argv[0],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ strncpy(ms->name, argv[1], sizeof(ms->name) - 1);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_ms, cfg_no_ms_cmd, "no ms MS_NAME",
+ NO_STR "Select a mobile station to remove\n"
+ "Name of MS (see \"show ms\")")
+{
+ struct osmocom_ms *ms;
+ int found = 0;
+
+ llist_for_each_entry(ms, &ms_list, entity) {
+ if (!strcmp(ms->name, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ vty_out(vty, "MS name '%s' does not exist%s", argv[0],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ mobile_delete(ms, 1);
+
+ return CMD_SUCCESS;
+}
+
#define SUP_WRITE(item, cmd) \
if (sup->item) \
vty_out(vty, " %s%s%s", (set->item) ? "" : "no ", cmd, \
@@ -878,6 +993,9 @@ static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
struct gsm_settings_abbrev *abbrev;
vty_out(vty, "ms %s%s", ms->name, VTY_NEWLINE);
+ vty_out(vty, " layer2-socket %s%s", set->layer2_socket_path,
+ VTY_NEWLINE);
+ vty_out(vty, " sap-socket %s%s", set->sap_socket_path, VTY_NEWLINE);
switch(set->sim_type) {
case GSM_SIM_TYPE_NONE:
vty_out(vty, " sim none%s", VTY_NEWLINE);
@@ -1011,6 +1129,8 @@ static void config_write_ms_single(struct vty *vty, struct osmocom_ms *ms)
vty_out(vty, " hplmn-search %s%s", (set->test_always) ? "everywhere"
: "foreign-country", VTY_NEWLINE);
vty_out(vty, " exit%s", VTY_NEWLINE);
+ vty_out(vty, " %sshutdown%s", (ms->shutdown) ? "" : "no ",
+ VTY_NEWLINE);
vty_out(vty, "exit%s", VTY_NEWLINE);
vty_out(vty, "!%s", VTY_NEWLINE);
}
@@ -1033,6 +1153,34 @@ static int config_write_ms(struct vty *vty)
return CMD_SUCCESS;
}
+DEFUN(cfg_ms_layer2, cfg_ms_layer2_cmd, "layer2-socket PATH",
+ "Define socket path to connect between layer 2 and layer 1\n"
+ "Unix socket, default '/tmp/osmocom_l2'")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ strncpy(set->layer2_socket_path, argv[0],
+ sizeof(set->layer2_socket_path) - 1);
+
+ vty_restart(vty, ms);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_sap, cfg_ms_sap_cmd, "sap-socket PATH",
+ "Define socket path to connect to SIM reader\n"
+ "Unix socket, default '/tmp/osmocom_sap'")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+
+ strncpy(set->sap_socket_path, argv[0],
+ sizeof(set->sap_socket_path) - 1);
+
+ vty_restart(vty, ms);
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
"Set SIM card type when powering on\nNo SIM interted\n"
"Use SIM from reader\nTest SIM inserted")
@@ -1055,7 +1203,7 @@ DEFUN(cfg_ms_sim, cfg_ms_sim_cmd, "sim (none|reader|test)",
return CMD_WARNING;
}
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1118,7 +1266,7 @@ DEFUN(cfg_ms_imei_fixed, cfg_ms_imei_fixed_cmd, "imei-fixed",
set->imei_random = 0;
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1131,7 +1279,7 @@ DEFUN(cfg_ms_imei_random, cfg_ms_imei_random_cmd, "imei-random <0-15>",
set->imei_random = atoi(argv[0]);
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1539,7 +1687,7 @@ DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
return CMD_WARNING; \
} \
if (restart) \
- vty_restart(vty); \
+ vty_restart(vty, ms); \
set->item = 1; \
return CMD_SUCCESS; \
}
@@ -1557,7 +1705,7 @@ DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
return CMD_WARNING; \
} \
if (restart) \
- vty_restart(vty); \
+ vty_restart(vty, ms); \
set->item = 0; \
return CMD_SUCCESS; \
}
@@ -1568,7 +1716,7 @@ DEFUN(cfg, cfg_cmd, cmd, "Enable " desc "support") \
struct osmocom_ms *ms = vty->index; \
struct gsm_settings *set = &ms->settings; \
if (restart) \
- vty_restart(vty); \
+ vty_restart(vty, ms); \
set->item = 1; \
return CMD_SUCCESS; \
}
@@ -1579,7 +1727,7 @@ DEFUN(cfg, cfg_cmd, "no " cmd, NO_STR "Disable " desc " support") \
struct osmocom_ms *ms = vty->index; \
struct gsm_settings *set = &ms->settings; \
if (restart) \
- vty_restart(vty); \
+ vty_restart(vty, ms); \
set->item = 0; \
return CMD_SUCCESS; \
}
@@ -1682,7 +1830,7 @@ DEFUN(cfg_ms_sup_ch_cap, cfg_ms_sup_ch_cap_cmd, "channel-capability "
if (ch_cap != set->ch_cap
&& (ch_cap == GSM_CAP_SDCCH || set->ch_cap == GSM_CAP_SDCCH))
- vty_restart(vty);
+ vty_restart(vty, ms);
set->ch_cap = ch_cap;
@@ -1759,7 +1907,7 @@ DEFUN(cfg_test_imsi, cfg_test_imsi_cmd, "imsi IMSI",
strcpy(set->test_imsi, argv[0]);
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1851,7 +1999,7 @@ DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
set->test_rplmn_valid = 0;
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1875,7 +2023,7 @@ DEFUN(cfg_test_rplmn, cfg_test_rplmn_cmd, "rplmn MCC MNC",
set->test_rplmn_mcc = mcc;
set->test_rplmn_mnc = mnc;
- vty_restart(vty);
+ vty_restart(vty, ms);
return CMD_SUCCESS;
}
@@ -1896,7 +2044,69 @@ DEFUN(cfg_test_hplmn, cfg_test_hplmn_cmd, "hplmn-search (everywhere|foreign-coun
break;
}
- vty_restart(vty);
+ vty_restart(vty, ms);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_shutdown, cfg_ms_no_shutdown_cmd, "no shutdown",
+ NO_STR "Activate and run MS")
+{
+ struct osmocom_ms *ms = vty->index, *tmp;
+ int rc;
+
+ if (ms->shutdown != 2)
+ return CMD_SUCCESS;
+
+ llist_for_each_entry(tmp, &ms_list, entity) {
+ if (tmp->shutdown == 2)
+ continue;
+ if (!strcmp(ms->settings.layer2_socket_path,
+ tmp->settings.layer2_socket_path)) {
+ vty_out(vty, "Cannot start MS '%s', because MS '%s' "
+ "use the same layer2-socket.%sPlease shutdown "
+ "MS '%s' first.%s", ms->name, tmp->name,
+ VTY_NEWLINE, tmp->name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (!strcmp(ms->settings.sap_socket_path,
+ tmp->settings.sap_socket_path)) {
+ vty_out(vty, "Cannot start MS '%s', because MS '%s' "
+ "use the same sap-socket.%sPlease shutdown "
+ "MS '%s' first.%s", ms->name, tmp->name,
+ VTY_NEWLINE, tmp->name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+
+ rc = l23_app_init(ms);
+ if (rc < 0) {
+ vty_out(vty, "Connection to layer 1 failed!%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_shutdown, cfg_ms_shutdown_cmd, "shutdown",
+ "Shut down and deactivate MS")
+{
+ struct osmocom_ms *ms = vty->index;
+
+ if (ms->shutdown == 0)
+ l23_app_exit(ms, 0);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_shutdown_force, cfg_ms_shutdown_force_cmd, "shutdown force",
+ "Shut down and deactivate MS\nDo not perform IMSI detach")
+{
+ struct osmocom_ms *ms = vty->index;
+
+ if (ms->shutdown <= 1)
+ l23_app_exit(ms, 1);
+
return CMD_SUCCESS;
}
@@ -1962,6 +2172,14 @@ gDEFUN(ournode_end,
return CMD_SUCCESS;
}
+DEFUN(off, off_cmd, "off",
+ "Turn mobiles off (shutdown) and exit")
+{
+ dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+
+ return CMD_SUCCESS;
+}
+
#define SUP_NODE(item) \
install_element(SUPPORT_NODE, &cfg_ms_sup_item_cmd);
@@ -1978,6 +2196,7 @@ int ms_vty_init(void)
install_element_ve(&show_forb_plmn_cmd);
install_element_ve(&monitor_network_cmd);
install_element_ve(&no_monitor_network_cmd);
+ install_element(ENABLE_NODE, &off_cmd);
install_element(ENABLE_NODE, &sim_test_cmd);
install_element(ENABLE_NODE, &sim_reader_cmd);
@@ -2001,11 +2220,16 @@ int ms_vty_init(void)
install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd);
install_element(CONFIG_NODE, &cfg_ms_cmd);
+ install_element(CONFIG_NODE, &cfg_ms_create_cmd);
+ install_element(CONFIG_NODE, &cfg_ms_rename_cmd);
+ install_element(CONFIG_NODE, &cfg_no_ms_cmd);
install_element(CONFIG_NODE, &ournode_end_cmd);
install_node(&ms_node, config_write_ms);
install_default(MS_NODE);
install_element(MS_NODE, &ournode_exit_cmd);
install_element(MS_NODE, &ournode_end_cmd);
+ install_element(MS_NODE, &cfg_ms_layer2_cmd);
+ install_element(MS_NODE, &cfg_ms_sap_cmd);
install_element(MS_NODE, &cfg_ms_sim_cmd);
install_element(MS_NODE, &cfg_ms_mode_cmd);
install_element(MS_NODE, &cfg_ms_imei_cmd);
@@ -2095,6 +2319,9 @@ int ms_vty_init(void)
install_element(TESTSIM_NODE, &cfg_test_no_rplmn_cmd);
install_element(TESTSIM_NODE, &cfg_test_rplmn_cmd);
install_element(TESTSIM_NODE, &cfg_test_hplmn_cmd);
+ install_element(MS_NODE, &cfg_ms_shutdown_cmd);
+ install_element(MS_NODE, &cfg_ms_shutdown_force_cmd);
+ install_element(MS_NODE, &cfg_ms_no_shutdown_cmd);
return 0;
}