summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/.gitignore1
-rw-r--r--openbsc/configure.ac4
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h1
-rw-r--r--openbsc/src/libbsc/bsc_vty.c37
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_filter.c66
-rw-r--r--openbsc/tests/Makefile.am4
-rw-r--r--openbsc/tests/atlocal.in1
-rw-r--r--openbsc/tests/bsc/Makefile.am19
-rw-r--r--openbsc/tests/bsc/bsc_test.c204
-rw-r--r--openbsc/tests/bsc/bsc_test.ok4
-rw-r--r--openbsc/tests/testsuite.at7
-rw-r--r--openbsc/tests/vty_test_runner.py34
12 files changed, 378 insertions, 4 deletions
diff --git a/openbsc/.gitignore b/openbsc/.gitignore
index 79222f7..5955482 100644
--- a/openbsc/.gitignore
+++ b/openbsc/.gitignore
@@ -63,6 +63,7 @@ tests/gprs/gprs_test
tests/abis/abis_test
tests/si/si_test
tests/smpp/smpp_test
+tests/bsc/bsc_test
tests/atconfig
tests/atlocal
diff --git a/openbsc/configure.ac b/openbsc/configure.ac
index ce2a328..ddd15e3 100644
--- a/openbsc/configure.ac
+++ b/openbsc/configure.ac
@@ -36,11 +36,12 @@ AC_SUBST(osmo_ac_build_nat)
# Enable/disable the BSC?
AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])],
- [osmo_ac_build_bsc="$enableval"])
+ [osmo_ac_build_bsc="$enableval"],[osmo_ac_build_bsc="no"])
if test "$osmo_ac_build_bsc" = "yes" ; then
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6)
fi
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
+AC_SUBST(osmo_ac_build_bsc)
# Enable/disable smpp support in the nitb?
AC_ARG_ENABLE([smpp], [AS_HELP_STRING([--enable-smpp], [Build the SMPP interface])],
@@ -156,6 +157,7 @@ AC_OUTPUT(
tests/gsm0408/Makefile
tests/db/Makefile
tests/channel/Makefile
+ tests/bsc/Makefile
tests/bsc-nat/Makefile
tests/bsc-nat-trie/Makefile
tests/mgcp/Makefile
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 3ef1457..437378a 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -594,6 +594,7 @@ struct gsm_bts {
int hr;
int mn;
int override;
+ int dst;
} tz;
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index d156716..5d03b2a 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -489,8 +489,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
VTY_NEWLINE);
vty_out(vty, " training_sequence_code %u%s", bts->tsc, VTY_NEWLINE);
vty_out(vty, " base_station_id_code %u%s", bts->bsic, VTY_NEWLINE);
- if (bts->tz.override != 0)
- vty_out(vty, " timezone %d %d%s", bts->tz.hr, bts->tz.mn, VTY_NEWLINE);
+ if (bts->tz.override != 0) {
+ if (bts->tz.dst)
+ vty_out(vty, " timezone %d %d %d%s",
+ bts->tz.hr, bts->tz.mn, bts->tz.dst, VTY_NEWLINE);
+ else
+ vty_out(vty, " timezone %d %d%s",
+ bts->tz.hr, bts->tz.mn, VTY_NEWLINE);
+ }
vty_out(vty, " ms max power %u%s", bts->ms_max_power, VTY_NEWLINE);
vty_out(vty, " cell reselection hysteresis %u%s",
bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
@@ -1621,6 +1627,32 @@ DEFUN(cfg_bts_timezone,
bts->tz.hr = tzhr;
bts->tz.mn = tzmn;
+ bts->tz.dst = 0;
+ bts->tz.override = 1;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_timezone_dst,
+ cfg_bts_timezone_dst_cmd,
+ "timezone <-19-19> (0|15|30|45) <0-2>",
+ "Set the Timezone Offset of this BTS\n"
+ "Timezone offset (hours)\n"
+ "Timezone offset (00 minutes)\n"
+ "Timezone offset (15 minutes)\n"
+ "Timezone offset (30 minutes)\n"
+ "Timezone offset (45 minutes)\n"
+ "DST offset (hours)\n"
+ )
+{
+ struct gsm_bts *bts = vty->index;
+ int tzhr = atoi(argv[0]);
+ int tzmn = atoi(argv[1]);
+ int tzdst = atoi(argv[2]);
+
+ bts->tz.hr = tzhr;
+ bts->tz.mn = tzmn;
+ bts->tz.dst = tzdst;
bts->tz.override = 1;
return CMD_SUCCESS;
@@ -3117,6 +3149,7 @@ int bsc_vty_init(const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_unit_id_cmd);
install_element(BTS_NODE, &cfg_bts_rsl_ip_cmd);
install_element(BTS_NODE, &cfg_bts_timezone_cmd);
+ install_element(BTS_NODE, &cfg_bts_timezone_dst_cmd);
install_element(BTS_NODE, &cfg_bts_no_timezone_cmd);
install_element(BTS_NODE, &cfg_bts_nokia_site_skip_reset_cmd);
install_element(BTS_NODE, &cfg_bts_stream_id_cmd);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 957ceaf..608f525 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -251,6 +251,65 @@ int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn)
return 0;
}
+static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn,
+ uint8_t *data, unsigned int length)
+{
+ struct tlv_parsed tp;
+ int parse_res;
+ struct gsm_bts *bts = conn->bts;
+ int tzunits;
+ uint8_t tzbsd = 0;
+ uint8_t dst = 0;
+
+ parse_res = tlv_parse(&tp, &gsm48_mm_att_tlvdef, data, length, 0, 0);
+ if (parse_res <= 0 && parse_res != -3)
+ return 0;
+
+ /* Is TZ patching enabled? */
+ if (!bts->tz.override)
+ return 0;
+
+ /* Convert tz.hr and tz.mn to units */
+ if (bts->tz.hr < 0) {
+ tzunits = -bts->tz.hr*4;
+ tzbsd |= 0x08;
+ } else
+ tzunits = bts->tz.hr*4;
+
+ tzunits = tzunits + (bts->tz.mn/15);
+
+ tzbsd |= (tzunits % 10)*0x10 + (tzunits / 10);
+
+ /* Convert DST value */
+ if (bts->tz.dst >= 0 && bts->tz.dst <= 2)
+ dst = bts->tz.dst;
+
+ if (TLVP_PRESENT(&tp, GSM48_IE_UTC)) {
+ LOGP(DMSC, LOGL_DEBUG,
+ "Changing 'Local time zone' from 0x%02x to 0x%02x.\n",
+ TLVP_VAL(&tp, GSM48_IE_UTC)[6], tzbsd);
+ ((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_UTC)))[0] = tzbsd;
+ }
+ if (TLVP_PRESENT(&tp, GSM48_IE_NET_TIME_TZ)) {
+ LOGP(DMSC, LOGL_DEBUG,
+ "Changing 'Universal time and local time zone' TZ from "
+ "0x%02x to 0x%02x.\n",
+ TLVP_VAL(&tp, GSM48_IE_NET_TIME_TZ)[6], tzbsd);
+ ((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_NET_TIME_TZ)))[6] = tzbsd;
+ }
+#ifdef GSM48_IE_NET_DST
+ if (TLVP_PRESENT(&tp, GSM48_IE_NET_DST)) {
+ LOGP(DMSC, LOGL_DEBUG,
+ "Changing 'Network daylight saving time' from "
+ "0x%02x to 0x%02x.\n",
+ TLVP_VAL(&tp, GSM48_IE_NET_DST)[0], dst);
+ ((uint8_t *)(TLVP_VAL(&tp, GSM48_IE_NET_DST)))[0] = dst;
+ }
+#endif
+
+ return 0;
+}
+
/**
* Messages coming back from the MSC.
*/
@@ -261,13 +320,16 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
struct gsm48_loc_area_id *lai;
struct gsm48_hdr *gh;
uint8_t mtype;
+ int length = msgb_l3len(msg);
- if (msgb_l3len(msg) < sizeof(*gh)) {
+ if (length < sizeof(*gh)) {
LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
return -1;
}
gh = (struct gsm48_hdr *) msgb_l3(msg);
+ length -= (const char *)&gh->data[0] - (const char *)gh;
+
mtype = gh->msg_type & 0xbf;
net = conn->bts->network;
msc = conn->sccp_con->msc;
@@ -285,6 +347,8 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
if (conn->sccp_con->new_subscriber)
return send_welcome_ussd(conn);
return 0;
+ } else if (mtype == GSM48_MT_MM_INFO) {
+ bsc_patch_mm_info(conn, &gh->data[0], length);
}
return 0;
diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am
index f2dc057..ed21fc3 100644
--- a/openbsc/tests/Makefile.am
+++ b/openbsc/tests/Makefile.am
@@ -4,6 +4,10 @@ if BUILD_NAT
SUBDIRS += bsc-nat bsc-nat-trie
endif
+if BUILD_BSC
+SUBDIRS += bsc
+endif
+
if BUILD_SMPP
SUBDIRS += smpp
endif
diff --git a/openbsc/tests/atlocal.in b/openbsc/tests/atlocal.in
index bfbecd4..4635113 100644
--- a/openbsc/tests/atlocal.in
+++ b/openbsc/tests/atlocal.in
@@ -1,2 +1,3 @@
enable_nat_test='@osmo_ac_build_nat@'
enable_smpp_test='@osmo_ac_build_smpp@'
+enable_bsc_test='@osmo_ac_build_bsc@'
diff --git a/openbsc/tests/bsc/Makefile.am b/openbsc/tests/bsc/Makefile.am
new file mode 100644
index 0000000..0c79b83
--- /dev/null
+++ b/openbsc/tests/bsc/Makefile.am
@@ -0,0 +1,19 @@
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(COVERAGE_LDFLAGS)
+
+EXTRA_DIST = bsc_test.ok
+
+noinst_PROGRAMS = bsc_test
+
+bsc_test_SOURCES = bsc_test.c \
+ $(top_srcdir)/src/osmo-bsc/osmo_bsc_filter.c
+bsc_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
+ $(top_builddir)/src/libmsc/libmsc.a \
+ $(top_builddir)/src/libctrl/libctrl.a \
+ $(top_builddir)/src/libmgcp/libmgcp.a \
+ $(top_builddir)/src/libtrau/libtrau.a \
+ $(top_builddir)/src/libcommon/libcommon.a \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -lrt \
+ $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) \
+ $(LIBOSMOABIS_LIBS)
diff --git a/openbsc/tests/bsc/bsc_test.c b/openbsc/tests/bsc/bsc_test.c
new file mode 100644
index 0000000..881c785
--- /dev/null
+++ b/openbsc/tests/bsc/bsc_test.c
@@ -0,0 +1,204 @@
+/*
+ * BSC Message filtering
+ *
+ * (C) 2013 by sysmocom s.f.m.c. GmbH
+ * Written by Jacob Erlbeck <jerlbeck@sysmocom.de>
+ * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2013 by On-Waves
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+
+#include <openbsc/osmo_bsc.h>
+#include <openbsc/osmo_msc_data.h>
+#include <openbsc/gsm_04_80.h>
+#include <openbsc/gsm_subscriber.h>
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/backtrace.h>
+#include <osmocom/core/talloc.h>
+
+#include <stdio.h>
+#include <search.h>
+
+enum test {
+ TEST_SCAN_TO_BTS,
+ TEST_SCAN_TO_MSC,
+};
+
+/* GSM 04.08 MM INFORMATION test message */
+static uint8_t gsm48_mm_info_nn_tzt[] = {
+ 0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
+ 0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
+ 0x11, 0x02, 0x73, 0x00,
+};
+
+static uint8_t gsm48_mm_info_nn_tzt_out[] = {
+ 0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
+ 0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
+ 0x11, 0x02, 0x73, 0x1a,
+};
+
+static uint8_t gsm48_mm_info_nn_tzt_dst[] = {
+ 0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
+ 0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
+ 0x11, 0x02, 0x73, 0x00, 0x49, 0x01, 0x00,
+};
+
+static uint8_t gsm48_mm_info_nn_tzt_dst_out[] = {
+ 0x05, 0x32, 0x45, 0x08, 0x80, 0x4f, 0x77, 0xeb,
+ 0x1a, 0xb6, 0x97, 0xe7, 0x47, 0x31, 0x90, 0x61,
+ 0x11, 0x02, 0x73, 0x1a, 0x49, 0x01, 0x02,
+};
+
+struct test_definition {
+ const uint8_t *data;
+ const uint16_t length;
+ const int dir;
+ const int result;
+ const uint8_t *out_data;
+ const uint16_t out_length;
+ const char* params;
+ const int n_params;
+};
+
+static int get_int(const char *params, size_t nmemb, const char *key, int def, int *is_set)
+{
+ const char *kv = NULL;
+
+ kv = strstr(params, key);
+ if (kv) {
+ kv += strlen(key) + 1;
+ fprintf(stderr, "get_int(%s) -> %d\n", key, atoi(kv));
+ if (is_set)
+ *is_set = 1;
+ }
+
+ return kv ? atoi(kv) : def;
+}
+
+static const struct test_definition test_scan_defs[] = {
+ {
+ .data = gsm48_mm_info_nn_tzt_dst,
+ .length = ARRAY_SIZE(gsm48_mm_info_nn_tzt),
+ .dir = TEST_SCAN_TO_BTS,
+ .result = 0,
+ .out_data = gsm48_mm_info_nn_tzt_dst_out,
+ .out_length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_out),
+ .params = "tz_hr=-5 tz_mn=15 tz_dst=2",
+ .n_params = 3,
+ },
+ {
+ .data = gsm48_mm_info_nn_tzt_dst,
+ .length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_dst),
+ .dir = TEST_SCAN_TO_BTS,
+ .result = 0,
+ .out_data = gsm48_mm_info_nn_tzt_dst_out,
+ .out_length = ARRAY_SIZE(gsm48_mm_info_nn_tzt_dst_out),
+ .params = "tz_hr=-5 tz_mn=15 tz_dst=2",
+ .n_params = 3,
+ },
+};
+
+static void test_scan(void)
+{
+ int i;
+
+ struct gsm_network *net;
+ struct gsm_bts *bts;
+ struct osmo_bsc_sccp_con *sccp_con;
+ struct osmo_msc_data *msc;
+ struct gsm_subscriber_connection *conn;
+
+ net = talloc_zero(NULL, struct gsm_network);
+ bts = talloc_zero(net, struct gsm_bts);
+ sccp_con = talloc_zero(net, struct osmo_bsc_sccp_con);
+ msc = talloc_zero(net, struct osmo_msc_data);
+ conn = talloc_zero(net, struct gsm_subscriber_connection);
+
+ bts->network = net;
+ sccp_con->msc = msc;
+ conn->bts = bts;
+ conn->sccp_con = sccp_con;
+
+ /* start testinh with proper messages */
+ printf("Testing BTS<->MSC message scan.\n");
+ for (i = 0; i < ARRAY_SIZE(test_scan_defs); ++i) {
+ const struct test_definition *test_def = &test_scan_defs[i];
+ int result;
+ struct msgb *msg = msgb_alloc(4096, "test-message");
+ int is_set = 0;
+
+ bts->tz.hr = get_int(test_def->params, test_def->n_params, "tz_hr", 0, &is_set);
+ bts->tz.mn = get_int(test_def->params, test_def->n_params, "tz_mn", 0, &is_set);
+ bts->tz.dst = get_int(test_def->params, test_def->n_params, "tz_dst", 0, &is_set);
+ bts->tz.override = get_int(test_def->params, test_def->n_params, "tz_dst", is_set ? 1 : 0, NULL);
+
+ printf("Going to test item: %d\n", i);
+ msg->l3h = msgb_put(msg, test_def->length);
+ memcpy(msg->l3h, test_def->data, test_def->length);
+
+ switch (test_def->dir) {
+ case TEST_SCAN_TO_BTS:
+ result = bsc_scan_msc_msg(conn, msg);
+ break;
+ case TEST_SCAN_TO_MSC:
+ result = bsc_scan_msc_msg(conn, msg);
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ if (result != test_def->result) {
+ printf("FAIL: Not the expected result, got: %d wanted: %d\n",
+ result, test_def->result);
+ goto out;
+ }
+
+ if (msgb_l3len(msg) != test_def->out_length) {
+ printf("FAIL: Not the expected message size, got: %d wanted: %d\n",
+ msgb_l3len(msg), test_def->out_length);
+ goto out;
+ }
+
+ if (memcmp(msgb_l3(msg), test_def->out_data, test_def->out_length) != 0) {
+ printf("FAIL: Not the expected message\n");
+ goto out;
+ }
+
+out:
+ msgb_free(msg);
+ }
+
+ talloc_free(net);
+}
+
+
+int main(int argc, char **argv)
+{
+ osmo_init_logging(&log_info);
+
+ test_scan();
+
+ printf("Testing execution completed.\n");
+ return 0;
+}
diff --git a/openbsc/tests/bsc/bsc_test.ok b/openbsc/tests/bsc/bsc_test.ok
new file mode 100644
index 0000000..0564bf0
--- /dev/null
+++ b/openbsc/tests/bsc/bsc_test.ok
@@ -0,0 +1,4 @@
+Testing BTS<->MSC message scan.
+Going to test item: 0
+Going to test item: 1
+Testing execution completed.
diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at
index e54d4b5..27225a8 100644
--- a/openbsc/tests/testsuite.at
+++ b/openbsc/tests/testsuite.at
@@ -68,3 +68,10 @@ AT_KEYWORDS([abis])
cat $abs_srcdir/abis/abis_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/abis/abis_test], [], [expout], [ignore])
AT_CLEANUP
+
+AT_SETUP([bsc])
+AT_KEYWORDS([bsc])
+AT_CHECK([test "$enable_bsc_test" != no || exit 77])
+cat $abs_srcdir/bsc/bsc_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/bsc/bsc_test], [], [expout], [ignore])
+AT_CLEANUP
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 46dbce7..3bb7bd8 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -315,6 +315,40 @@ class TestVTYBSC(TestVTYGenericBSC):
self.assertEquals(res.find('missing-msc-text No MSC found'), -1)
self.assert_(res.find('no missing-msc-text') > 0)
+ def testNetworkTimezone(self):
+ self.vty.enable()
+ self.vty.verify("configure terminal", [''])
+ self.vty.verify("network", [''])
+ self.vty.verify("bts 0", [''])
+
+ # Test invalid input
+ self.vty.verify("timezone", ['% Command incomplete.'])
+ self.vty.verify("timezone 20 0", ['% Unknown command.'])
+ self.vty.verify("timezone 0 11", ['% Unknown command.'])
+ self.vty.verify("timezone 0 0 99", ['% Unknown command.'])
+
+ # Set time zone without DST
+ self.vty.verify("timezone 2 30", [''])
+
+ # Verify settings
+ res = self.vty.command("write terminal")
+ self.assert_(res.find('timezone 2 30') > 0)
+ self.assertEquals(res.find('timezone 2 30 '), -1)
+
+ # Set time zone with DST
+ self.vty.verify("timezone 2 30 1", [''])
+
+ # Verify settings
+ res = self.vty.command("write terminal")
+ self.assert_(res.find('timezone 2 30 1') > 0)
+
+ # Now disable it..
+ self.vty.verify("no timezone", [''])
+
+ # Verify settings
+ res = self.vty.command("write terminal")
+ self.assertEquals(res.find(' timezone'), -1)
+
class TestVTYNAT(TestVTYGenericBSC):
def vty_command(self):