1 /* CCCH passive sniffer */
2 /* (C) 2010-2011 by Holger Hans Peter Freyther
3 * (C) 2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <osmocore/msgb.h>
28 #include <osmocore/rsl.h>
29 #include <osmocore/tlv.h>
30 #include <osmocore/gsm48_ie.h>
31 #include <osmocore/gsm48.h>
32 #include <osmocore/signal.h>
33 #include <osmocore/protocol/gsm_04_08.h>
35 #include <osmocom/bb/common/logging.h>
36 #include <osmocom/bb/common/lapdm.h>
37 #include <osmocom/bb/misc/rslms.h>
38 #include <osmocom/bb/misc/layer3.h>
39 #include <osmocom/bb/common/osmocom_data.h>
40 #include <osmocom/bb/common/l1ctl.h>
41 #include <osmocom/bb/common/l23_app.h>
48 struct gsm_sysinfo_freq cell_arfcns[1024];
52 static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
54 struct gsm48_system_information_type_header *si_hdr;
55 si_hdr = (struct gsm48_system_information_type_header *) data;
57 /* GSM 05.02 ยง6.3.1.3 Mapping of BCCH data */
58 switch (si_hdr->system_information) {
59 case GSM48_MT_RR_SYSINFO_1:
62 LOGP(DRR, LOGL_ERROR, "SI1 on the wrong TC: %d\n", tc);
64 if (!app_state.has_si1) {
65 struct gsm48_system_information_type_1 *si1 =
66 (struct gsm48_system_information_type_1 *)data;
68 gsm48_decode_freq_list(app_state.cell_arfcns,
69 si1->cell_channel_description,
70 sizeof(si1->cell_channel_description),
73 app_state.has_si1 = 1;
74 LOGP(DRR, LOGL_ERROR, "SI1 received.\n");
77 case GSM48_MT_RR_SYSINFO_2:
80 LOGP(DRR, LOGL_ERROR, "SI2 on the wrong TC: %d\n", tc);
83 case GSM48_MT_RR_SYSINFO_3:
85 if (tc != 2 && tc != 6)
86 LOGP(DRR, LOGL_ERROR, "SI3 on the wrong TC: %d\n", tc);
88 if (app_state.ccch_mode == CCCH_MODE_NONE) {
89 struct gsm48_system_information_type_3 *si3 =
90 (struct gsm48_system_information_type_3 *)data;
92 if (si3->control_channel_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C)
93 app_state.ccch_mode = CCCH_MODE_COMBINED;
95 app_state.ccch_mode = CCCH_MODE_NON_COMBINED;
97 l1ctl_tx_ccch_mode_req(ms, app_state.ccch_mode);
100 case GSM48_MT_RR_SYSINFO_4:
102 if (tc != 3 && tc != 7)
103 LOGP(DRR, LOGL_ERROR, "SI4 on the wrong TC: %d\n", tc);
106 case GSM48_MT_RR_SYSINFO_5:
108 case GSM48_MT_RR_SYSINFO_6:
110 case GSM48_MT_RR_SYSINFO_7:
113 LOGP(DRR, LOGL_ERROR, "SI7 on the wrong TC: %d\n", tc);
116 case GSM48_MT_RR_SYSINFO_8:
119 LOGP(DRR, LOGL_ERROR, "SI8 on the wrong TC: %d\n", tc);
122 case GSM48_MT_RR_SYSINFO_9:
125 LOGP(DRR, LOGL_ERROR, "SI9 on the wrong TC: %d\n", tc);
128 case GSM48_MT_RR_SYSINFO_13:
130 if (tc != 4 && tc != 0)
131 LOGP(DRR, LOGL_ERROR, "SI13 on the wrong TC: %d\n", tc);
134 case GSM48_MT_RR_SYSINFO_16:
137 LOGP(DRR, LOGL_ERROR, "SI16 on the wrong TC: %d\n", tc);
140 case GSM48_MT_RR_SYSINFO_17:
143 LOGP(DRR, LOGL_ERROR, "SI17 on the wrong TC: %d\n", tc);
146 case GSM48_MT_RR_SYSINFO_2bis:
149 LOGP(DRR, LOGL_ERROR, "SI2bis on the wrong TC: %d\n", tc);
152 case GSM48_MT_RR_SYSINFO_2ter:
154 if (tc != 5 && tc != 4)
155 LOGP(DRR, LOGL_ERROR, "SI2ter on the wrong TC: %d\n", tc);
158 case GSM48_MT_RR_SYSINFO_5bis:
160 case GSM48_MT_RR_SYSINFO_5ter:
163 fprintf(stderr, "\tUnknown SI");
170 * This method used to send a l1ctl_tx_dm_est_req_h0 or
171 * a l1ctl_tx_dm_est_req_h1 to the layer1 to follow this
172 * assignment. The code has been removed.
174 static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
176 struct gsm48_imm_ass *ia = msgb_l3(msg);
177 uint8_t ch_type, ch_subch, ch_ts;
179 /* Discard packet TBF assignement */
180 if (ia->page_mode & 0xf0)
183 /* FIXME: compare RA and GSM time with when we sent RACH req */
185 rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
187 if (!ia->chan_desc.h0.h) {
191 arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
193 LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
194 "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
195 ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
196 ia->chan_desc.h0.tsc);
200 uint8_t maio, hsn, ma_len;
201 uint16_t ma[64], arfcn;
204 hsn = ia->chan_desc.h1.hsn;
205 maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);
207 LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
208 "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
209 ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
210 ia->chan_desc.h1.tsc);
212 /* decode mobile allocation */
214 for (i=1, j=0; i<=1024; i++) {
216 if (app_state.cell_arfcns[arfcn].mask & 0x01) {
217 k = ia->mob_alloc_len - (j>>3) - 1;
218 if (ia->mob_alloc[k] & (1 << (j&7))) {
219 ma[ma_len++] = arfcn;
226 LOGPC(DRR, LOGL_NOTICE, "\n");
230 static const char *pag_print_mode(int mode)
234 return "Normal paging";
236 return "Extended paging";
238 return "Paging reorganization";
240 return "Same as before";
246 static char *chan_need(int need)
262 static char *mi_type_to_string(int type)
265 case GSM_MI_TYPE_NONE:
267 case GSM_MI_TYPE_IMSI:
269 case GSM_MI_TYPE_IMEI:
271 case GSM_MI_TYPE_IMEISV:
273 case GSM_MI_TYPE_TMSI:
281 * This can contain two MIs. The size checking is a bit of a mess.
283 static int gsm48_rx_paging_p1(struct msgb *msg, struct osmocom_ms *ms)
285 struct gsm48_paging1 *pag;
286 int len1, len2, mi_type, tag;
287 char mi_string[GSM48_MI_SIZE];
289 /* is there enough room for the header + LV? */
290 if (msgb_l3len(msg) < sizeof(*pag) + 2) {
291 LOGP(DRR, LOGL_ERROR, "PagingRequest is too short.\n");
297 mi_type = pag->data[1] & GSM_MI_TYPE_MASK;
299 if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1) {
300 LOGP(DRR, LOGL_ERROR, "PagingRequest with wrong MI\n");
304 if (mi_type != GSM_MI_TYPE_NONE) {
305 gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[1], len1);
306 LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to %s M(%s) \n",
307 pag_print_mode(pag->pag_mode),
308 chan_need(pag->cneed1),
309 mi_type_to_string(mi_type),
313 /* check if we have a MI type in here */
314 if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1 + 3)
317 tag = pag->data[2 + len1 + 0];
318 len2 = pag->data[2 + len1 + 1];
319 mi_type = pag->data[2 + len1 + 2] & GSM_MI_TYPE_MASK;
320 if (tag == GSM48_IE_MOBILE_ID && mi_type != GSM_MI_TYPE_NONE) {
321 if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1 + 3 + len2) {
322 LOGP(DRR, LOGL_ERROR, "Optional MI does not fit here.\n");
326 gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[2 + len1 + 2], len2);
327 LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to %s M(%s) \n",
328 pag_print_mode(pag->pag_mode),
329 chan_need(pag->cneed2),
330 mi_type_to_string(mi_type),
336 static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
338 struct gsm48_paging2 *pag;
339 int tag, len, mi_type;
340 char mi_string[GSM48_MI_SIZE];
342 if (msgb_l3len(msg) < sizeof(*pag)) {
343 LOGP(DRR, LOGL_ERROR, "Paging2 message is too small.\n");
348 LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
349 pag_print_mode(pag->pag_mode),
350 chan_need(pag->cneed1), pag->tmsi1);
351 LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
352 pag_print_mode(pag->pag_mode),
353 chan_need(pag->cneed1), pag->tmsi2);
355 /* no optional element */
356 if (msgb_l3len(msg) < sizeof(*pag) + 3)
361 mi_type = pag->data[2] & GSM_MI_TYPE_MASK;
363 if (tag != GSM48_IE_MOBILE_ID)
366 if (msgb_l3len(msg) < sizeof(*pag) + 3 + len) {
367 LOGP(DRR, LOGL_ERROR, "Optional MI does not fit in here\n");
371 gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[2], len);
372 LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to %s M(%s) \n",
373 pag_print_mode(pag->pag_mode),
375 mi_type_to_string(mi_type),
381 int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
383 struct gsm48_system_information_type_header *sih = msgb_l3(msg);
386 if (sih->rr_protocol_discriminator != GSM48_PDISC_RR)
387 LOGP(DRR, LOGL_ERROR, "PCH pdisc != RR\n");
389 switch (sih->system_information) {
390 case GSM48_MT_RR_PAG_REQ_1:
391 gsm48_rx_paging_p1(msg, ms);
393 case GSM48_MT_RR_PAG_REQ_2:
394 gsm48_rx_paging_p2(msg, ms);
396 case GSM48_MT_RR_PAG_REQ_3:
397 LOGP(DRR, LOGL_ERROR, "PAGING of type 3 is not implemented.\n");
399 case GSM48_MT_RR_IMM_ASS:
400 gsm48_rx_imm_ass(msg, ms);
402 case GSM48_MT_RR_NOTIF_NCH:
403 /* notification for voice call groups and such */
406 /* wireshark know that this is SI2 quater and for 3G interop */
409 LOGP(DRR, LOGL_NOTICE, "unknown PCH/AGCH type 0x%02x\n",
410 sih->system_information);
417 int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms)
419 /* FIXME: we have lost the gsm frame time until here, need to store it
420 * in some msgb context */
421 //dump_bcch(dl->time.tc, ccch->data);
422 dump_bcch(ms, 0, msg->l3h);
424 /* Req channel logic */
425 if (app_state.ccch_enabled && (app_state.rach_count < 2)) {
426 l1ctl_tx_rach_req(ms, app_state.rach_count, 0,
427 app_state.ccch_mode == CCCH_MODE_COMBINED);
428 app_state.rach_count++;
434 void layer3_app_reset(void)
437 app_state.has_si1 = 0;
438 app_state.ccch_mode = CCCH_MODE_NONE;
439 app_state.ccch_enabled = 0;
440 app_state.rach_count = 0;
442 memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns));
445 static int signal_cb(unsigned int subsys, unsigned int signal,
446 void *handler_data, void *signal_data)
448 struct osmocom_ms *ms;
450 if (subsys != SS_L1CTL)
457 return l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
458 L1CTL_FBSB_F_FB01SB, 100, 0,
466 int l23_app_init(struct osmocom_ms *ms)
468 register_signal_handler(SS_L1CTL, &signal_cb, NULL);
469 l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
470 return layer3_init(ms);
473 static struct l23_app_info info = {
474 .copyright = "Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>\n",
475 .contribution = "Contributions by Holger Hans Peter Freyther\n",
478 struct l23_app_info *l23_app_info()