summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src/misc
diff options
context:
space:
mode:
authorAlex Badea <vamposdecampos@gmail.com>2010-11-21 22:46:11 +0200
committerHarald Welte <laforge@gnumonks.org>2010-11-21 23:33:27 +0100
commit689c0e5f8dac7aef9f2cce4e52b02d446e4b1cbd (patch)
treecb2a52904a0c35c69f5397c95a58ad27c5323433 /src/host/layer23/src/misc
parent30f17f5dd7d090e68e1eeb63b681b22676009061 (diff)
host layer23: add a small cbch_sniff application
Tune to the ARFCN specified on the commandline (-a). Then, if a CBCH Channel Description IE is found in System Information Type 4, switch to dedicated mode on that particular channel to receive the CBCH.
Diffstat (limited to 'src/host/layer23/src/misc')
-rw-r--r--src/host/layer23/src/misc/Makefile.am5
-rw-r--r--src/host/layer23/src/misc/app_cbch_sniff.c188
2 files changed, 190 insertions, 3 deletions
diff --git a/src/host/layer23/src/misc/Makefile.am b/src/host/layer23/src/misc/Makefile.am
index da2628e5..f8a0b737 100644
--- a/src/host/layer23/src/misc/Makefile.am
+++ b/src/host/layer23/src/misc/Makefile.am
@@ -2,7 +2,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS)
LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS)
-bin_PROGRAMS = bcch_scan layer23 echo_test cell_log
+bin_PROGRAMS = bcch_scan layer23 echo_test cell_log cbch_sniff
bcch_scan_SOURCES = ../common/main.c app_bcch_scan.c bcch_scan.c
layer23_SOURCES = ../common/main.c app_phone.c layer3.c rslms.c
@@ -10,5 +10,4 @@ echo_test_SOURCES = ../common/main.c app_echo_test.c
cell_log_LDADD = $(LDADD) -lm
cell_log_SOURCES = ../common/main.c app_cell_log.c cell_log.c \
../../../gsmmap/geo.c
-
-
+cbch_sniff_SOURCES = ../common/main.c app_cbch_sniff.c
diff --git a/src/host/layer23/src/misc/app_cbch_sniff.c b/src/host/layer23/src/misc/app_cbch_sniff.c
new file mode 100644
index 00000000..19a9aced
--- /dev/null
+++ b/src/host/layer23/src/misc/app_cbch_sniff.c
@@ -0,0 +1,188 @@
+/* CBCH passive sniffer */
+
+/* (C) 2010 by Holger Hans Peter Freyther
+ * (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Alex Badea <vamposdecampos@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 <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/common/lapdm.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/misc/layer3.h>
+
+#include <osmocore/msgb.h>
+#include <osmocore/talloc.h>
+#include <osmocore/select.h>
+#include <osmocore/signal.h>
+#include <osmocore/rsl.h>
+
+struct osmocom_ms *g_ms;
+struct gsm48_sysinfo g_sysinfo = {};
+
+static int try_cbch(struct osmocom_ms *ms, struct gsm48_sysinfo *s)
+{
+ if (!s->si1 || !s->si4)
+ return 0;
+ if (!s->chan_nr) {
+ LOGP(DRR, LOGL_INFO, "no CBCH chan_nr found\n");
+ return 0;
+ }
+
+ if (s->h) {
+ LOGP(DRR, LOGL_INFO, "chan_nr = 0x%02x TSC = %d MAIO = %d "
+ "HSN = %d hseq (%d): %s\n",
+ s->chan_nr, s->tsc, s->maio, s->hsn,
+ s->hopp_len,
+ hexdump((unsigned char *) s->hopping, s->hopp_len * 2));
+ return l1ctl_tx_dm_est_req_h1(ms,
+ s->maio, s->hsn, s->hopping, s->hopp_len,
+ s->chan_nr, s->tsc,
+ GSM48_CMODE_SIGN);
+ } else {
+ LOGP(DRR, LOGL_INFO, "chan_nr = 0x%02x TSC = %d ARFCN = %d\n",
+ s->chan_nr, s->tsc, s->arfcn);
+ return l1ctl_tx_dm_est_req_h0(ms, s->arfcn,
+ s->chan_nr, s->tsc, GSM48_CMODE_SIGN);
+ }
+}
+
+
+/* receive BCCH at RR layer */
+static int bcch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ struct gsm48_sysinfo *s = &g_sysinfo;
+
+ if (msgb_l3len(msg) != 23) {
+ LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
+ return -EINVAL;
+ }
+ switch (sih->system_information) {
+ case GSM48_MT_RR_SYSINFO_1:
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
+ gsm48_decode_sysinfo1(s,
+ (struct gsm48_system_information_type_1 *) sih,
+ msgb_l3len(msg));
+ return try_cbch(ms, s);
+ case GSM48_MT_RR_SYSINFO_4:
+ LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
+ gsm48_decode_sysinfo4(s,
+ (struct gsm48_system_information_type_4 *) sih,
+ msgb_l3len(msg));
+ return try_cbch(ms, s);
+ default:
+ return 0;
+ }
+}
+
+static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ struct tlv_parsed tv;
+ uint8_t ch_type, ch_subch, ch_ts;
+
+ DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
+ rllh->chan_nr, rllh->link_id);
+
+ rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
+ if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
+ DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
+ return -EIO;
+ }
+ msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
+
+ rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
+ switch (ch_type) {
+ case RSL_CHAN_BCCH:
+ return bcch(ms, msg);
+ default:
+ return 0;
+ }
+}
+
+static int rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ int msg_type = rllh->c.msg_type;
+
+ if (msg_type == RSL_MT_UNIT_DATA_IND) {
+ unit_data_ind(ms, msg);
+ } else
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+
+ msgb_free(msg);
+
+ return 0;
+}
+
+static int rcv_rsl(struct msgb *msg, struct osmocom_ms *ms)
+{
+ struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+ int rc = 0;
+
+ switch (rslh->msg_discr & 0xfe) {
+ case ABIS_RSL_MDISC_RLL:
+ rc = rcv_rll(ms, msg);
+ break;
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
+ rslh->msg_discr);
+ msgb_free(msg);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+static int signal_cb(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
+{
+ struct osmocom_ms *ms;
+
+ if (subsys != SS_L1CTL)
+ return 0;
+
+ switch (signal) {
+ case S_L1CTL_RESET:
+ case S_L1CTL_FBSB_ERR:
+ ms = g_ms;
+ return l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_COMBINED);
+ case S_L1CTL_FBSB_RESP:
+ return 0;
+ }
+ return 0;
+}
+
+int l23_app_init(struct osmocom_ms *ms)
+{
+ /* don't do layer3_init() as we don't want an actualy L3 */
+
+ g_ms = ms;
+ osmol2_register_handler(ms, &rcv_rsl);
+
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ /* FIXME: L1CTL_RES_T_FULL doesn't reset dedicated mode
+ * (if previously set), so we release it here. */
+ l1ctl_tx_dm_rel_req(ms);
+ return register_signal_handler(SS_L1CTL, &signal_cb, NULL);
+}