blob: dba793309bd10b5acde2afb0d4da6734b2fe47da [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* A hackish minimal BSC (+MSC +HLR) implementation */
2
3/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
Harald Weltef6b7a902008-12-26 00:05:11 +000022#include <unistd.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <stdarg.h>
26#include <time.h>
27#include <string.h>
Harald Weltead384642008-12-26 10:20:07 +000028#include <errno.h>
Harald Welted1252502009-01-01 01:50:32 +000029#include <signal.h>
Harald Welte52b1f982008-12-23 20:25:15 +000030
Holger Freytherb332f612008-12-27 12:46:51 +000031#define _GNU_SOURCE
32#include <getopt.h>
33
Harald Welte255539c2008-12-28 02:26:27 +000034#include <openbsc/db.h>
35#include <openbsc/timer.h>
Harald Welte8470bf22008-12-25 23:28:35 +000036#include <openbsc/gsm_data.h>
Harald Welte255539c2008-12-28 02:26:27 +000037#include <openbsc/gsm_04_08.h>
Harald Weltead384642008-12-26 10:20:07 +000038#include <openbsc/select.h>
Harald Welte8470bf22008-12-25 23:28:35 +000039#include <openbsc/abis_rsl.h>
40#include <openbsc/abis_nm.h>
Harald Welte702d8702008-12-26 20:25:35 +000041#include <openbsc/debug.h>
Holger Freyther5677ae32008-12-27 09:41:03 +000042#include <openbsc/misdn.h>
Harald Welte52b1f982008-12-23 20:25:15 +000043
44/* global pointer to the gsm network data structure */
45static struct gsm_network *gsmnet;
46
Holger Freytherefde7fb2008-12-28 14:14:56 +000047/* MCC and MNC for the Location Area Identifier */
48static int MCC = 1;
49static int MNC = 1;
Holger Freytherbde36102008-12-28 22:51:39 +000050static const char *database_name = "hlr.sqlite3";
Holger Freytherefde7fb2008-12-28 14:14:56 +000051
Holger Freyther07cc8d82008-12-29 06:23:46 +000052/* forward declarations */
Holger Freytherb7193e42008-12-29 17:44:08 +000053static void bsc_hack_update_request(struct gsm_bts *bts,
54 u_int32_t assigned_tmi, int accepted);
Holger Freyther3186bf22008-12-29 06:23:49 +000055static void bsc_hack_channel_allocated(struct gsm_lchan *chan,
56 enum gsm_chreq_reason_t reason);
Holger Freyther88ea8322008-12-29 06:23:52 +000057static void bsc_hack_channel_response(struct gsm_lchan *chan, int acked);
Holger Freytherb7193e42008-12-29 17:44:08 +000058static void bsc_hack_call_state_changed(struct gsm_lchan *chan,
59 enum gsm_call_state new_state);
Holger Freyther07cc8d82008-12-29 06:23:46 +000060
Holger Freytherefde7fb2008-12-28 14:14:56 +000061
Harald Welte52b1f982008-12-23 20:25:15 +000062/* The following definitions are for OM and NM packets that we cannot yet
63 * generate by code but we just pass on */
64
65// BTS Site Manager, SET ATTRIBUTES
66
67/*
68 Object Class: BTS Site Manager
69 Instance 1: FF
70 Instance 2: FF
71 Instance 3: FF
72SET ATTRIBUTES
73 sAbisExternalTime: 2007/09/08 14:36:11
74 omLAPDRelTimer: 30sec
75 shortLAPDIntTimer: 5sec
76 emergencyTimer1: 10 minutes
77 emergencyTimer2: 0 minutes
78*/
79
80unsigned char msg_1[] =
81{
82 0xD0, 0x00, 0xFF, 0xFF, 0xFF, 0x91, 0x07, 0xD7, 0x09, 0x08, 0x0E, 0x24,
83 0x0B, 0xCE, 0x02, 0x00, 0x1E, 0xE8, 0x01, 0x05, 0x42, 0x02, 0x00, 0x0A, 0x44,
84 0x02, 0x00, 0x00
85};
86
87// BTS, SET BTS ATTRIBUTES
88
89/*
90 Object Class: BTS
91 BTS relat. Number: 0
92 Instance 2: FF
93 Instance 3: FF
94SET BTS ATTRIBUTES
95 bsIdentityCode / BSIC:
96 PLMN_colour_code: 7h
97 BS_colour_code: 7h
98 BTS Air Timer T3105: 4 ,unit 10 ms
99 btsIsHopping: FALSE
100 periodCCCHLoadIndication: 255sec
101 thresholdCCCHLoadIndication: 100%
102 cellAllocationNumber: 00h = GSM 900
103 enableInterferenceClass: 00h = Disabled
104 fACCHQual: 6 (FACCH stealing flags minus 1)
105 intaveParameter: 31 SACCH multiframes
106 interferenceLevelBoundaries:
107 Interference Boundary 1: 0Ah
108 Interference Boundary 2: 0Fh
109 Interference Boundary 3: 14h
110 Interference Boundary 4: 19h
111 Interference Boundary 5: 1Eh
112 mSTxPwrMax: 11
113 GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
114 DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
115 PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
116 30=33dBm, 31=32dBm
117 ny1:
118 Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
119 powerOutputThresholds:
120 Out Power Fault Threshold: -10 dB
121 Red Out Power Threshold: - 6 dB
122 Excessive Out Power Threshold: 5 dB
123 rACHBusyThreshold: -127 dBm
124 rACHLoadAveragingSlots: 250 ,number of RACH burst periods
125 rfResourceIndicationPeriod: 125 SACCH multiframes
126 T200:
127 SDCCH: 044 in 5 ms
128 FACCH/Full rate: 031 in 5 ms
129 FACCH/Half rate: 041 in 5 ms
130 SACCH with TCH SAPI0: 090 in 10 ms
131 SACCH with SDCCH: 090 in 10 ms
132 SDCCH with SAPI3: 090 in 5 ms
133 SACCH with TCH SAPI3: 135 in 10 ms
134 tSync: 9000 units of 10 msec
135 tTrau: 9000 units of 10 msec
136 enableUmLoopTest: 00h = disabled
137 enableExcessiveDistance: 00h = Disabled
138 excessiveDistance: 64km
139 hoppingMode: 00h = baseband hopping
140 cellType: 00h = Standard Cell
141 BCCH ARFCN / bCCHFrequency: 1
142*/
143
144unsigned char msg_2[] =
145{
146 0x41, 0x01, 0x00, 0xFF, 0xFF, 0x09, 0x3F, 0x0A, 0x04, 0x61, 0x00, 0x0B,
147 0xFF, 0x0C, 0x64, 0x62, 0x00, 0x66, 0x00, 0x6E, 0x06, 0x18, 0x1F, 0x19,
148 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B, 0x0B, 0x23, 0x14, 0x28, 0x00, 0x04,
149 0x03, 0x2A, 0x7F, 0x2B, 0x00, 0xFA, 0x8F, 0x7D, 0x33, 0x2C, 0x1F, 0x29,
150 0x5A, 0x5A, 0x5A, 0x87, 0x94, 0x23, 0x28, 0x95, 0x23, 0x28, 0x35, 0x01,
151 0x00, 0x46, 0x01, 0x00, 0x58, 0x01, 0x40, 0xC5, 0x01, 0x00, 0xF2, 0x01,
152 0x00, 0x08, 0x00, HARDCODED_ARFCN/*0x01*/,
153};
154
155// Handover Recognition, SET ATTRIBUTES
156
157/*
158Illegal Contents GSM Formatted O&M Msg
159 Object Class: Handover Recognition
160 BTS relat. Number: 0
161 Instance 2: FF
162 Instance 3: FF
163SET ATTRIBUTES
164 enableDelayPowerBudgetHO: 00h = Disabled
165 enableDistanceHO: 00h = Disabled
166 enableInternalInterCellHandover: 00h = Disabled
167 enableInternalIntraCellHandover: 00h = Disabled
168 enablePowerBudgetHO: 00h = Disabled
169 enableRXLEVHO: 00h = Disabled
170 enableRXQUALHO: 00h = Disabled
171 hoAveragingDistance: 8 SACCH multiframes
172 hoAveragingLev:
173 A_LEV_HO: 8 SACCH multiframes
174 W_LEV_HO: 1 SACCH multiframes
175 hoAveragingPowerBudget: 16 SACCH multiframes
176 hoAveragingQual:
177 A_QUAL_HO: 8 SACCH multiframes
178 W_QUAL_HO: 2 SACCH multiframes
179 hoLowerThresholdLevDL: (10 - 110) dBm
180 hoLowerThresholdLevUL: (5 - 110) dBm
181 hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
182 hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
183 hoThresholdLevDLintra : (20 - 110) dBm
184 hoThresholdLevULintra: (20 - 110) dBm
185 hoThresholdMsRangeMax: 20 km
186 nCell: 06h
187 timerHORequest: 3 ,unit 2 SACCH multiframes
188*/
189
190unsigned char msg_3[] =
191{
192 0xD0, 0xA1, 0x00, 0xFF, 0xFF, 0xD0, 0x00, 0x64, 0x00, 0x67, 0x00, 0x68,
193 0x00, 0x6A, 0x00, 0x6C, 0x00, 0x6D, 0x00, 0x6F, 0x08, 0x70, 0x08, 0x01,
194 0x71, 0x10, 0x10, 0x10, 0x72, 0x08, 0x02, 0x73, 0x0A, 0x74, 0x05, 0x75,
195 0x06, 0x76, 0x06, 0x78, 0x14, 0x79, 0x14, 0x7A, 0x14, 0x7D, 0x06, 0x92,
196 0x03, 0x20, 0x01, 0x00, 0x45, 0x01, 0x00, 0x48, 0x01, 0x00, 0x5A, 0x01,
197 0x00, 0x5B, 0x01, 0x05, 0x5E, 0x01, 0x1A, 0x5F, 0x01, 0x20, 0x9D, 0x01,
198 0x00, 0x47, 0x01, 0x00, 0x5C, 0x01, 0x64, 0x5D, 0x01, 0x1E, 0x97, 0x01,
199 0x20, 0xF7, 0x01, 0x3C,
200};
201
202// Power Control, SET ATTRIBUTES
203
204/*
205 Object Class: Power Control
206 BTS relat. Number: 0
207 Instance 2: FF
208 Instance 3: FF
209SET ATTRIBUTES
210 enableMsPowerControl: 00h = Disabled
211 enablePowerControlRLFW: 00h = Disabled
212 pcAveragingLev:
213 A_LEV_PC: 4 SACCH multiframes
214 W_LEV_PC: 1 SACCH multiframes
215 pcAveragingQual:
216 A_QUAL_PC: 4 SACCH multiframes
217 W_QUAL_PC: 2 SACCH multiframes
218 pcLowerThresholdLevDL: 0Fh
219 pcLowerThresholdLevUL: 0Ah
220 pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
221 pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
222 pcRLFThreshold: 0Ch
223 pcUpperThresholdLevDL: 14h
224 pcUpperThresholdLevUL: 0Fh
225 pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
226 pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
227 powerConfirm: 2 ,unit 2 SACCH multiframes
228 powerControlInterval: 2 ,unit 2 SACCH multiframes
229 powerIncrStepSize: 02h = 4 dB
230 powerRedStepSize: 01h = 2 dB
231 radioLinkTimeoutBs: 64 SACCH multiframes
232 enableBSPowerControl: 00h = disabled
233*/
234
235unsigned char msg_4[] =
236{
237 0xD0, 0xA2, 0x00, 0xFF, 0xFF, 0x69, 0x00, 0x6B, 0x00, 0x7E, 0x04, 0x01,
238 0x7F, 0x04, 0x02, 0x80, 0x0F, 0x81, 0x0A, 0x82, 0x05, 0x83, 0x05, 0x84,
239 0x0C, 0x85, 0x14, 0x86, 0x0F, 0x87, 0x04, 0x88, 0x04, 0x89, 0x02, 0x8A,
240 0x02, 0x8B, 0x02, 0x8C, 0x01, 0x8D, 0x40, 0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
241};
242
243
244// Transceiver, SET TRX ATTRIBUTES (TRX 0)
245
246/*
247 Object Class: Transceiver
248 BTS relat. Number: 0
249 Tranceiver number: 0
250 Instance 3: FF
251SET TRX ATTRIBUTES
252 aRFCNList (HEX): 0001
253 txPwrMaxReduction: 00h = 0dB
254 radioMeasGran: 254 SACCH multiframes
255 radioMeasRep: 01h = enabled
256 memberOfEmergencyConfig: 01h = TRUE
257 trxArea: 00h = TRX doesn't belong to a concentric cell
258*/
259
260unsigned char msg_6[] =
261{
262 0x44, 0x02, 0x00, 0x00, 0xFF, 0x05, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/, 0x2D,
263 0x00, 0xDC, 0x01, 0xFE, 0xDD, 0x01, 0x01, 0x9B, 0x01, 0x01, 0x9F, 0x01, 0x00,
264};
265
266
267static void bootstrap_om(struct gsm_bts *bts)
268{
269 struct gsm_bts_trx *trx = &bts->trx[0];
270
Harald Weltead384642008-12-26 10:20:07 +0000271 fprintf(stdout, "bootstrapping OML\n");
272
Harald Welte52b1f982008-12-23 20:25:15 +0000273 /* stop sending event reports */
274 abis_nm_event_reports(bts, 0);
275
276 /* begin DB transmission */
277 abis_nm_db_transmission(bts, 1);
278
Harald Welte702d8702008-12-26 20:25:35 +0000279 /* end DB transmission */
280 abis_nm_db_transmission(bts, 0);
281
282 /* Reset BTS Site manager resource */
283 abis_nm_reset_resource(bts);
284
285 /* begin DB transmission */
286 abis_nm_db_transmission(bts, 1);
287
Harald Welte52b1f982008-12-23 20:25:15 +0000288 abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
289 abis_nm_raw_msg(bts, sizeof(msg_2), msg_2); /* set BTS attr */
290 abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
291 abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
292
293 /* Connect signalling of bts0/trx0 to e1_0/ts1/64kbps */
294 abis_nm_conn_terr_sign(trx, 0, 1, 0xff);
295 abis_nm_raw_msg(bts, sizeof(msg_6), msg_6); /* SET TRX ATTRIBUTES */
296
297 /* Use TEI 1 for signalling */
298 abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x01);
299 abis_nm_set_channel_attr(&trx->ts[0], NM_CHANC_SDCCH_CBCH);
300#if 0
301 /* TRX 1 */
302 abis_nm_conn_terr_sign(&bts->trx[1], 0, 1, 0xff);
303 /* FIXME: TRX ATTRIBUTE */
304 abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x02);
305#endif
306
307 /* SET CHANNEL ATTRIBUTE TS1 */
308 abis_nm_set_channel_attr(&trx->ts[1], 0x09);
309 /* Connect traffic of bts0/trx0/ts1 to e1_0/ts2/b */
310 abis_nm_conn_terr_traf(&trx->ts[1], 0, 2, 1);
311
312 /* SET CHANNEL ATTRIBUTE TS2 */
313 abis_nm_set_channel_attr(&trx->ts[2], 0x09);
314 /* Connect traffic of bts0/trx0/ts2 to e1_0/ts2/c */
315 abis_nm_conn_terr_traf(&trx->ts[2], 0, 2, 2);
316
317 /* SET CHANNEL ATTRIBUTE TS3 */
318 abis_nm_set_channel_attr(&trx->ts[3], 0x09);
319 /* Connect traffic of bts0/trx0/ts3 to e1_0/ts2/d */
320 abis_nm_conn_terr_traf(&trx->ts[3], 0, 2, 3);
321
322 /* SET CHANNEL ATTRIBUTE TS4 */
323 abis_nm_set_channel_attr(&trx->ts[4], 0x09);
324 /* Connect traffic of bts0/trx0/ts4 to e1_0/ts3/a */
325 abis_nm_conn_terr_traf(&trx->ts[4], 0, 3, 0);
326
327 /* SET CHANNEL ATTRIBUTE TS5 */
328 abis_nm_set_channel_attr(&trx->ts[5], 0x09);
329 /* Connect traffic of bts0/trx0/ts5 to e1_0/ts3/b */
330 abis_nm_conn_terr_traf(&trx->ts[5], 0, 3, 1);
331
332 /* SET CHANNEL ATTRIBUTE TS6 */
333 abis_nm_set_channel_attr(&trx->ts[6], 0x09);
334 /* Connect traffic of bts0/trx0/ts6 to e1_0/ts3/c */
335 abis_nm_conn_terr_traf(&trx->ts[6], 0, 3, 2);
336
337 /* SET CHANNEL ATTRIBUTE TS7 */
338 abis_nm_set_channel_attr(&trx->ts[7], 0x09);
339 /* Connect traffic of bts0/trx0/ts7 to e1_0/ts3/d */
340 abis_nm_conn_terr_traf(&trx->ts[7], 0, 3, 3);
341
342 /* end DB transmission */
343 abis_nm_db_transmission(bts, 0);
344
345 /* Reset BTS Site manager resource */
346 abis_nm_reset_resource(bts);
347
348 /* restart sending event reports */
349 abis_nm_event_reports(bts, 1);
350}
351
Harald Welted1252502009-01-01 01:50:32 +0000352static int shutdown_om(struct gsm_bts *bts)
353{
354 /* stop sending event reports */
355 abis_nm_event_reports(bts, 0);
Harald Welte52b1f982008-12-23 20:25:15 +0000356
Harald Welted1252502009-01-01 01:50:32 +0000357 /* begin DB transmission */
358 abis_nm_db_transmission(bts, 1);
359
360 /* end DB transmission */
361 abis_nm_db_transmission(bts, 0);
362
363 /* Reset BTS Site manager resource */
364 abis_nm_reset_resource(bts);
365
366 return 0;
367}
368
369static int shutdown_net(struct gsm_network *net)
370{
371 int i;
372 for (i = 0; i < net->num_bts; i++) {
373 int rc;
374 rc = shutdown_om(&net->bts[i]);
375 if (rc < 0)
376 return rc;
377 }
378
379 return 0;
380}
Harald Welte52b1f982008-12-23 20:25:15 +0000381
382struct bcch_info {
383 u_int8_t type;
384 u_int8_t len;
385 const u_int8_t *data;
386};
387
388/*
389SYSTEM INFORMATION TYPE 1
390 Cell channel description
391 Format-ID bit map 0
392 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
393 RACH Control Parameters
394 maximum 7 retransmissions
395 8 slots used to spread transmission
396 cell not barred for access
397 call reestablishment not allowed
398 Access Control Class = 0000
399*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000400static u_int8_t si1[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000401 /* header */0x55, 0x06, 0x19,
402 /* ccdesc */0x04 /*0x00*/, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*0x01*/,
404 /* rach */0xD5, 0x00, 0x00,
405 /* s1 reset*/0x2B
Harald Welte52b1f982008-12-23 20:25:15 +0000406};
407
408/*
409 SYSTEM INFORMATION TYPE 2
410 Neighbour Cells Description
411 EXT-IND: Carries the complete BA
412 BA-IND = 0
413 Format-ID bit map 0
414 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
415 NCC permitted (NCC) = FF
416 RACH Control Parameters
417 maximum 7 retransmissions
418 8 slots used to spread transmission
419 cell not barred for access
420 call reestablishment not allowed
421 Access Control Class = 0000
422*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000423static u_int8_t si2[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000424 /* header */0x59, 0x06, 0x1A,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 /* ncc */0xFF,
428 /* rach*/0xD5, 0x00, 0x00
Harald Welte52b1f982008-12-23 20:25:15 +0000429};
430
431/*
432SYSTEM INFORMATION TYPE 3
433 Cell identity = 00001 (1h)
434 Location area identification
435 Mobile Country Code (MCC): 001
436 Mobile Network Code (MNC): 01
437 Location Area Code (LAC): 00001 (1h)
438 Control Channel Description
439 Attach-detach: MSs in the cell are not allowed to apply IMSI attach /detach
440 0 blocks reserved for access grant
441 1 channel used for CCCH, with SDCCH
442 5 multiframes period for PAGING REQUEST
443 Time-out T3212 = 0
444 Cell Options BCCH
445 Power control indicator: not set
446 MSs shall not use uplink DTX
447 Radio link timeout = 36
448 Cell Selection Parameters
449 Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
Harald Welte3b2ec422008-12-29 04:11:14 +0000450 max.TX power level MS may use for CCH = 2 <- according to GSM05.05 39dBm (max)
Harald Welte52b1f982008-12-23 20:25:15 +0000451 Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
452 Half rate support (NECI): New establishment causes are not supported
453 min.RX signal level for MS = 0
454 RACH Control Parameters
455 maximum 7 retransmissions
456 8 slots used to spread transmission
457 cell not barred for access
458 call reestablishment not allowed
459 Access Control Class = 0000
460 SI 3 Rest Octets
461 Cell Bar Qualify (CBQ): 0
462 Cell Reselect Offset = 0 dB
463 Temporary Offset = 0 dB
464 Penalty Time = 20 s
465 System Information 2ter Indicator (2TI): 0 = not available
466 Early Classmark Sending Control (ECSC): 0 = forbidden
467 Scheduling Information is not sent in SYSTEM INFORMATION TYPE 9 on the BCCH
468*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000469static u_int8_t si3[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000470 /* header */0x49, 0x06, 0x1B,
471 /* cell */0x00, 0x01,
472 /* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
473 /* desc */0x01, 0x03, 0x00,
474 /* option*/0x28,
475 /* selection*/0x62, 0x00,
476 /* rach */0xD5, 0x00, 0x00,
477 /* reset*/0x80, 0x00, 0x00, 0x2B
Harald Welte52b1f982008-12-23 20:25:15 +0000478};
479
480/*
481SYSTEM INFORMATION TYPE 4
482 Location area identification
483 Mobile Country Code (MCC): 001
484 Mobile Network Code (MNC): 01
485 Location Area Code (LAC): 00001 (1h)
486 Cell Selection Parameters
487 Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
488 max.TX power level MS may use for CCH = 2
489 Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
490 Half rate support (NECI): New establishment causes are not supported
491 min.RX signal level for MS = 0
492 RACH Control Parameters
493 maximum 7 retransmissions
494 8 slots used to spread transmission
495 cell not barred for access
496 call reestablishment not allowed
497 Access Control Class = 0000
498 Channel Description
499 Type = SDCCH/4[2]
500 Timeslot Number: 0
501 Training Sequence Code: 7h
502 ARFCN: 1
503 SI Rest Octets
504 Cell Bar Qualify (CBQ): 0
505 Cell Reselect Offset = 0 dB
506 Temporary Offset = 0 dB
507 Penalty Time = 20 s
508*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000509static u_int8_t si4[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000510 /* header */0x41, 0x06, 0x1C,
511 /* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
512 /* sel */0x62, 0x00,
513 /* rach*/0xD5, 0x00, 0x00,
514 /* var */0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/, 0x80, 0x00, 0x00,
Harald Welte52b1f982008-12-23 20:25:15 +0000515 0x2B, 0x2B, 0x2B
516};
517
518/*
519 SYSTEM INFORMATION TYPE 5
520 Neighbour Cells Description
521 EXT-IND: Carries the complete BA
522 BA-IND = 0
523 Format-ID bit map 0
524 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
525*/
526
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000527static u_int8_t si5[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000528 /* header without l2 len*/0x06, 0x1D,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Harald Welte52b1f982008-12-23 20:25:15 +0000531};
532
533// SYSTEM INFORMATION TYPE 6
534
535/*
536SACCH FILLING
537 System Info Type: SYSTEM INFORMATION 6
538 L3 Information (Hex): 06 1E 00 01 xx xx 10 00 01 28 FF
539
540SYSTEM INFORMATION TYPE 6
541 Cell identity = 00001 (1h)
542 Location area identification
543 Mobile Country Code (MCC): 001
544 Mobile Network Code (MNC): 01
545 Location Area Code (LAC): 00001 (1h)
546 Cell Options SACCH
547 Power control indicator: not set
548 MSs shall not use uplink DTX on a TCH-F. MS shall not use uplink DTX on TCH-H.
549 Radio link timeout = 36
550 NCC permitted (NCC) = FF
551*/
552
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000553static u_int8_t si6[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000554 /* header */0x06, 0x1E,
555 /* cell id*/ 0x00, 0x01,
556 /* lai */ 0x00, 0xF1, 0x10, 0x00, 0x01,
557 /* options */ 0x28,
558 /* ncc */ 0xFF,
Harald Welte52b1f982008-12-23 20:25:15 +0000559};
560
561
562
563static const struct bcch_info bcch_infos[] = {
564 {
565 .type = RSL_SYSTEM_INFO_1,
566 .len = sizeof(si1),
567 .data = si1,
568 }, {
569 .type = RSL_SYSTEM_INFO_2,
570 .len = sizeof(si2),
571 .data = si2,
572 }, {
573 .type = RSL_SYSTEM_INFO_3,
574 .len = sizeof(si3),
575 .data = si3,
576 }, {
577 .type = RSL_SYSTEM_INFO_4,
578 .len = sizeof(si4),
579 .data = si4,
580 },
581};
582
Holger Freyther24287b62008-12-28 16:32:41 +0000583static_assert(sizeof(si1) == sizeof(struct gsm48_system_information_type_1), type1)
584static_assert(sizeof(si2) == sizeof(struct gsm48_system_information_type_2), type2)
585static_assert(sizeof(si3) == sizeof(struct gsm48_system_information_type_3), type3)
586static_assert(sizeof(si4) >= sizeof(struct gsm48_system_information_type_4), type4)
Harald Welte104604e2008-12-28 16:36:11 +0000587static_assert(sizeof(si5) == sizeof(struct gsm48_system_information_type_5), type5)
588static_assert(sizeof(si6) >= sizeof(struct gsm48_system_information_type_6), type6)
Holger Freyther24287b62008-12-28 16:32:41 +0000589
Harald Welte52b1f982008-12-23 20:25:15 +0000590/* set all system information types */
591static int set_system_infos(struct gsm_bts *bts)
592{
593 int i;
594
595 for (i = 0; i < ARRAY_SIZE(bcch_infos); i++) {
596 rsl_bcch_info(bts, bcch_infos[i].type,
597 bcch_infos[i].data,
598 bcch_infos[i].len);
599 }
600 rsl_sacch_filling(bts, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
601 rsl_sacch_filling(bts, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
Harald Weltead384642008-12-26 10:20:07 +0000602
603 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000604}
605
606static void activate_traffic_channels(struct gsm_bts_trx *trx)
607{
608 int i;
609
610 /* channel 0 is CCCH */
611 for (i = 1; i < 8; i++)
612 rsl_chan_activate_tch_f(&trx->ts[i]);
613}
614
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000615/*
616 * Patch the various SYSTEM INFORMATION tables to update
617 * the LAI
618 */
619static void patch_tables(struct gsm_bts *bts)
620{
621 /* covert the raw packet to the struct */
622 struct gsm48_system_information_type_3 *type_3 =
623 (struct gsm48_system_information_type_3*)&si3;
624 struct gsm48_system_information_type_4 *type_4 =
625 (struct gsm48_system_information_type_4*)&si4;
626 struct gsm48_system_information_type_6 *type_6 =
627 (struct gsm48_system_information_type_6*)&si6;
Harald Welteb84e2f42008-12-28 23:42:04 +0000628 struct gsm48_loc_area_id lai;
629
630 gsm0408_generate_lai(&lai, bts->network->country_code,
631 bts->network->network_code, bts->location_area_code);
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000632
633 /* assign the MCC and MNC */
Harald Welteb84e2f42008-12-28 23:42:04 +0000634 type_3->lai = lai;
635 type_4->lai = lai;
636 type_6->lai = lai;
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000637}
638
639
Harald Weltead384642008-12-26 10:20:07 +0000640static void bootstrap_rsl(struct gsm_bts *bts)
Harald Welte52b1f982008-12-23 20:25:15 +0000641{
Harald Welteb84e2f42008-12-28 23:42:04 +0000642 fprintf(stdout, "bootstrapping RSL MCC=%u MNC=%u\n", MCC, MNC);
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000643 patch_tables(bts);
Harald Welte52b1f982008-12-23 20:25:15 +0000644 set_system_infos(bts);
645
646 /* FIXME: defer this until the channels are used */
Harald Welte702d8702008-12-26 20:25:35 +0000647 //activate_traffic_channels(&bts->trx[0]);
Harald Welte52b1f982008-12-23 20:25:15 +0000648}
649
Harald Weltead384642008-12-26 10:20:07 +0000650static void mi_cb(int event, struct gsm_bts *bts)
651{
652 switch (event) {
653 case EVT_E1_OML_UP:
654 bootstrap_om(bts);
655 break;
656 case EVT_E1_RSL_UP:
657 bootstrap_rsl(bts);
658 break;
659 default:
660 /* FIXME: deal with TEI or L1 link loss */
661 break;
662 }
663}
664
665static int bootstrap_network(void)
Harald Welte52b1f982008-12-23 20:25:15 +0000666{
667 struct gsm_bts *bts;
668
669 /* initialize our data structures */
Holger Freytherefde7fb2008-12-28 14:14:56 +0000670 gsmnet = gsm_network_init(1, MCC, MNC);
Harald Weltead384642008-12-26 10:20:07 +0000671 if (!gsmnet)
672 return -ENOMEM;
Harald Weltef5cbab72008-12-30 18:00:15 +0000673
674 gsmnet->name_short = "25C3";
675 gsmnet->name_long = "25C3 GSM";
Harald Welte52b1f982008-12-23 20:25:15 +0000676 bts = &gsmnet->bts[0];
677 bts->location_area_code = 1;
678 bts->trx[0].arfcn = HARDCODED_ARFCN;
Harald Weltef5cbab72008-12-30 18:00:15 +0000679#if 0
Holger Freytherb7193e42008-12-29 17:44:08 +0000680 gsmnet->update_request = bsc_hack_update_request;
Holger Freyther3186bf22008-12-29 06:23:49 +0000681 gsmnet->channel_allocated = bsc_hack_channel_allocated;
Holger Freyther88ea8322008-12-29 06:23:52 +0000682 gsmnet->channel_response = bsc_hack_channel_response;
Holger Freytherb7193e42008-12-29 17:44:08 +0000683 gsmnet->call_state_changed = bsc_hack_call_state_changed;
Harald Weltef5cbab72008-12-30 18:00:15 +0000684#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000685
Harald Weltead384642008-12-26 10:20:07 +0000686 if (mi_setup(bts, 0, mi_cb) < 0)
687 return -EIO;
688
689 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000690}
Harald Weltef6b7a902008-12-26 00:05:11 +0000691
Holger Freytherb332f612008-12-27 12:46:51 +0000692static void print_usage()
693{
694 printf("Usage: bsc_hack\n");
695}
696
697static void print_help()
698{
699 printf(" Some useful help...\n");
700 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
Holger Freytherefde7fb2008-12-28 14:14:56 +0000701 printf(" -s --disable-color\n");
702 printf(" -n --network-code number(MNC) \n");
703 printf(" -c --country-code number (MCC) \n");
Holger Freytherbde36102008-12-28 22:51:39 +0000704 printf(" -l --database db-name The database to use\n");
Holger Freyther89824fc2008-12-30 16:18:18 +0000705 printf(" -a --authorize-everyone Allow everyone into the network.\n");
Holger Freythere97f7fb2008-12-31 18:52:11 +0000706 printf(" -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
Holger Freytherb332f612008-12-27 12:46:51 +0000707 printf(" -h --help this text\n");
708}
709
710static void handle_options(int argc, char** argv)
711{
712 while (1) {
713 int option_index = 0, c;
714 static struct option long_options[] = {
715 {"help", 0, 0, 'h'},
716 {"debug", 1, 0, 'd'},
Holger Freytherefde7fb2008-12-28 14:14:56 +0000717 {"disable-color", 0, 0, 's'},
718 {"network-code", 1, 0, 'n'},
719 {"country-code", 1, 0, 'c'},
Holger Freytherbde36102008-12-28 22:51:39 +0000720 {"database", 1, 0, 'l'},
Holger Freyther89824fc2008-12-30 16:18:18 +0000721 {"authorize-everyone", 0, 0, 'a'},
Holger Freythere97f7fb2008-12-31 18:52:11 +0000722 {"reject-cause", 1, 0, 'r'},
Holger Freytherb332f612008-12-27 12:46:51 +0000723 {0, 0, 0, 0}
724 };
725
Holger Freythere97f7fb2008-12-31 18:52:11 +0000726 c = getopt_long(argc, argv, "hc:n:d:sar:",
Holger Freytherb332f612008-12-27 12:46:51 +0000727 long_options, &option_index);
728 if (c == -1)
729 break;
730
731 switch (c) {
732 case 'h':
733 print_usage();
734 print_help();
735 exit(0);
Holger Freytherefde7fb2008-12-28 14:14:56 +0000736 case 's':
Holger Freytherb332f612008-12-27 12:46:51 +0000737 debug_use_color(0);
738 break;
739 case 'd':
740 debug_parse_category_mask(optarg);
741 break;
Holger Freytherefde7fb2008-12-28 14:14:56 +0000742 case 'n':
743 MNC = atoi(optarg);
744 break;
745 case 'c':
746 MCC = atoi(optarg);
747 break;
Holger Freytherbde36102008-12-28 22:51:39 +0000748 case 'l':
749 database_name = strdup(optarg);
750 break;
Holger Freyther89824fc2008-12-30 16:18:18 +0000751 case 'a':
752 gsm0408_allow_everyone(1);
753 break;
Holger Freythere97f7fb2008-12-31 18:52:11 +0000754 case 'r':
755 gsm0408_set_reject_cause(atoi(optarg));
756 break;
Holger Freytherb332f612008-12-27 12:46:51 +0000757 default:
758 /* ignore */
759 break;
760 }
761 }
762}
763
Harald Welte255539c2008-12-28 02:26:27 +0000764static struct timer_list pag_timer;
765
766/* handles uppercase decimal and hexadecimal */
767static u_int8_t char2bcd(char c)
768{
769 if (c <= '9')
770 return c - '0';
771 else
772 return c - 'A';
773}
774
775static int string_to_mi(u_int8_t *mi, const char *string,
776 u_int8_t type)
777{
778 u_int8_t *cur = mi+3;
779
780 mi[0] = GSM48_IE_MOBILE_ID;
781 //mi[1] = TMSI_LEN;
782 mi[2] = type & GSM_MI_TYPE_MASK;
783
784 if (strlen(string) & 0x01)
785 mi[2] |= char2bcd(*string++) << 4;
786 else
787 mi[2] |= 0xf0;
788
789 while (*string && *(string+1))
790 *cur++ = char2bcd(*string++) | (char2bcd(*string++) << 4);
791
792 mi[1] = cur - mi;
793
794 return cur - mi;
795}
796
Holger Freyther07cc8d82008-12-29 06:23:46 +0000797/*
798 * Stations that registered and that we need to page
799 */
800struct pending_registered_station {
801 struct llist_head entry;
Harald Welte255539c2008-12-28 02:26:27 +0000802
Holger Freyther07cc8d82008-12-29 06:23:46 +0000803 /* the tmsi of the subscriber */
804 u_int32_t tmsi;
805 int last_page_group;
806};
807
808static LLIST_HEAD(pending_stations);
809
810static void pag_timer_cb(void *data);
811static struct timer_list pag_timer = {
812 .cb = pag_timer_cb,
813};
814
815/* page the tmsi and wait for the channel request */
816static void pag_timer_cb(void *data)
Harald Welte255539c2008-12-28 02:26:27 +0000817{
818 struct gsm_bts *bts = &gsmnet->bts[0];
Holger Freyther07cc8d82008-12-29 06:23:46 +0000819 struct pending_registered_station *pending_station;
Harald Welte255539c2008-12-28 02:26:27 +0000820 u_int8_t mi[128];
Holger Freyther07cc8d82008-12-29 06:23:46 +0000821 unsigned int mi_len;
Harald Welte255539c2008-12-28 02:26:27 +0000822
Harald Welte21768812009-01-01 00:32:49 +0000823return;
Harald Weltef5cbab72008-12-30 18:00:15 +0000824
Holger Freyther07cc8d82008-12-29 06:23:46 +0000825 if (llist_empty(&pending_stations)) {
826 DEBUGP(DPAG, "pag_timer_cb but no pending mobile stations\n");
Harald Welte255539c2008-12-28 02:26:27 +0000827 return;
Holger Freyther07cc8d82008-12-29 06:23:46 +0000828 }
Harald Welte255539c2008-12-28 02:26:27 +0000829
Holger Freyther07cc8d82008-12-29 06:23:46 +0000830 /* get the station to page */
831 pending_station = (struct pending_registered_station*) pending_stations.next;
832 mi_len = generate_mid_from_tmsi(mi, pending_station->tmsi);
833 rsl_paging_cmd(bts, pending_station->last_page_group, mi_len, mi, RSL_CHANNEED_TCH_F);
Harald Welte255539c2008-12-28 02:26:27 +0000834
Holger Freyther07cc8d82008-12-29 06:23:46 +0000835 /* which group to page next */
836 pending_station->last_page_group = (pending_station->last_page_group+1) % 12;
837 schedule_timer(&pag_timer, 1, 0);
838}
Harald Welte255539c2008-12-28 02:26:27 +0000839
Holger Freyther07cc8d82008-12-29 06:23:46 +0000840/*
841 * initiate the a page command for the given
842 * station and retry until we get a channel request
843 */
844static void station_timer_cb(void *data)
845{
846 DEBUGP(DPAG, "Initiating paging of a channel\n");
847 pag_timer_cb(0);
848}
Harald Welte255539c2008-12-28 02:26:27 +0000849
Holger Freyther07cc8d82008-12-29 06:23:46 +0000850static struct timer_list station_timer = {
851 .cb = station_timer_cb,
852};
853
854/*
855 * schedule work
856 */
Holger Freytherb7193e42008-12-29 17:44:08 +0000857static void bsc_hack_update_request(struct gsm_bts *bts, u_int32_t tmsi, int accepted)
Holger Freyther07cc8d82008-12-29 06:23:46 +0000858{
859 struct pending_registered_station *station =
860 (struct pending_registered_station*)malloc(sizeof(*station));
Holger Freytherb7193e42008-12-29 17:44:08 +0000861
862 /*
863 * Only deal with LOCATION UPDATE REQUEST we have
864 * accepted.
865 */
866 if (!accepted)
867 return;
868
869
Holger Freyther07cc8d82008-12-29 06:23:46 +0000870 station->tmsi = tmsi;
871 station->last_page_group = 0;
872 llist_add_tail(&station->entry, &pending_stations);
873
874 if (!timer_pending(&station_timer))
875 schedule_timer(&station_timer, 1, 0);
Harald Welte255539c2008-12-28 02:26:27 +0000876}
877
Holger Freyther3186bf22008-12-29 06:23:49 +0000878static void bsc_hack_channel_allocated(struct gsm_lchan *chan,
879 enum gsm_chreq_reason_t chreq_reason)
880{
881 struct pending_registered_station *station;
882 if (chreq_reason != GSM_CHREQ_REASON_PAG)
883 return;
884
885 if (llist_empty(&pending_stations)) {
886 DEBUGP(DPAG, "Channel allocated for pag but not waitin for it\n");
887 return;
888 }
889
890 station = (struct pending_registered_station*) pending_stations.next;
891
892 DEBUGP(DPAG, "CHAN RQD due PAG %d on %d for %u\n", chan->type, chan->nr, station->tmsi);
893
894 /* allocate some token in the chan for us */
895 chan->user_data = (void*)station->tmsi;
896 del_timer(&pag_timer);
897}
898
Holger Freyther88ea8322008-12-29 06:23:52 +0000899static void bsc_hack_channel_response(struct gsm_lchan *lchan, int ack)
Holger Freyther24893de2008-12-29 06:23:51 +0000900{
901 struct pending_registered_station *station;
902 if (llist_empty(&pending_stations)) {
Holger Freyther24893de2008-12-29 06:23:51 +0000903 return;
904 }
905
906 station = (struct pending_registered_station*) pending_stations.next;
907 if (station->tmsi != (u_int32_t)lchan->user_data) {
908 DEBUGP(DPAG, "Hmmm the channel is not allocated by the"
909 "station we wanted channel: %u us:%u\n",
910 (u_int32_t)(lchan->user_data), station->tmsi);
911 return;
912 }
913
Holger Freyther88ea8322008-12-29 06:23:52 +0000914 if (ack) {
915 DEBUGP(DPAG, "We have probably paged a channel for tmsi: %u on %d\n",
916 station->tmsi, lchan->nr);
Holger Freyther24893de2008-12-29 06:23:51 +0000917
Holger Freyther88ea8322008-12-29 06:23:52 +0000918 llist_del(&station->entry);
919 free(station);
Holger Freytherabade7a2008-12-29 06:42:15 +0000920
921 /*
922 * start a call
923 */
924 gsm48_cc_tx_setup(lchan);
Holger Freyther88ea8322008-12-29 06:23:52 +0000925 } else {
926 /*
927 * give up and go to the next channel
928 */
929 llist_del(&station->entry);
930 free(station);
931 pag_timer_cb(0);
Holger Freyther24893de2008-12-29 06:23:51 +0000932 }
Holger Freyther24893de2008-12-29 06:23:51 +0000933}
934
Holger Freytherb7193e42008-12-29 17:44:08 +0000935static void bsc_hack_call_state_changed(struct gsm_lchan *lchan,
936 enum gsm_call_state new_state)
Holger Freyther2eafef52008-12-29 06:42:17 +0000937{
938 DEBUGP(DPAG, "Call released jumping to the next...\n");
Holger Freytherb7193e42008-12-29 17:44:08 +0000939
940 /* only handle the transition back to the NULL state */
941 if (new_state != GSM_CSTATE_NULL)
942 return;
943
Holger Freyther2eafef52008-12-29 06:42:17 +0000944 rsl_chan_release(lchan);
945
946 /* next!!! */
947 pag_timer_cb(0);
948}
949
Harald Welted1252502009-01-01 01:50:32 +0000950static void signal_handler(int signal)
951{
952 fprintf(stdout, "signal %u received\n", signal);
953
954 switch (signal) {
955 case SIGHUP:
956 case SIGABRT:
957 shutdown_net(gsmnet);
958 break;
959 default:
960 break;
961 }
962}
963
Harald Weltef6b7a902008-12-26 00:05:11 +0000964int main(int argc, char **argv)
965{
Holger Freytherb332f612008-12-27 12:46:51 +0000966 /* parse options */
967 handle_options(argc, argv);
968
Holger Freytherbde36102008-12-28 22:51:39 +0000969 if (db_init(database_name)) {
Harald Welte75a983f2008-12-27 21:34:06 +0000970 printf("DB: Failed to init database. Please check the option settings.\n");
971 return 1;
972 }
973 printf("DB: Database initialized.\n");
974
975 if (db_prepare()) {
976 printf("DB: Failed to prepare database.\n");
977 return 1;
978 }
979 printf("DB: Database prepared.\n");
980
Harald Weltef6b7a902008-12-26 00:05:11 +0000981 bootstrap_network();
982
Harald Welted1252502009-01-01 01:50:32 +0000983 signal(SIGHUP, &signal_handler);
984 signal(SIGABRT, &signal_handler);
985
Harald Weltef6b7a902008-12-26 00:05:11 +0000986 while (1) {
987 bsc_select_main();
988 }
989}