blob: 0087de277bde265d090bf56aa293246799d45871 [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 Welte52b1f982008-12-23 20:25:15 +000029
Holger Freytherb332f612008-12-27 12:46:51 +000030#define _GNU_SOURCE
31#include <getopt.h>
32
Harald Welte255539c2008-12-28 02:26:27 +000033#include <openbsc/db.h>
34#include <openbsc/timer.h>
Harald Welte8470bf22008-12-25 23:28:35 +000035#include <openbsc/gsm_data.h>
Harald Welte255539c2008-12-28 02:26:27 +000036#include <openbsc/gsm_04_08.h>
Harald Weltead384642008-12-26 10:20:07 +000037#include <openbsc/select.h>
Harald Welte8470bf22008-12-25 23:28:35 +000038#include <openbsc/abis_rsl.h>
39#include <openbsc/abis_nm.h>
Harald Welte702d8702008-12-26 20:25:35 +000040#include <openbsc/debug.h>
Holger Freyther5677ae32008-12-27 09:41:03 +000041#include <openbsc/misdn.h>
Harald Welte52b1f982008-12-23 20:25:15 +000042
43/* global pointer to the gsm network data structure */
44static struct gsm_network *gsmnet;
45
Holger Freytherefde7fb2008-12-28 14:14:56 +000046/* MCC and MNC for the Location Area Identifier */
47static int MCC = 1;
48static int MNC = 1;
Holger Freytherbde36102008-12-28 22:51:39 +000049static const char *database_name = "hlr.sqlite3";
Holger Freytherefde7fb2008-12-28 14:14:56 +000050
Holger Freyther07cc8d82008-12-29 06:23:46 +000051/* forward declarations */
52static void bsc_hack_update_request_accepted(struct gsm_bts *bts, u_int32_t assigned_tmi);
Holger Freyther3186bf22008-12-29 06:23:49 +000053static void bsc_hack_channel_allocated(struct gsm_lchan *chan,
54 enum gsm_chreq_reason_t reason);
Holger Freyther88ea8322008-12-29 06:23:52 +000055static void bsc_hack_channel_response(struct gsm_lchan *chan, int acked);
Holger Freyther07cc8d82008-12-29 06:23:46 +000056
Holger Freytherefde7fb2008-12-28 14:14:56 +000057
Harald Welte52b1f982008-12-23 20:25:15 +000058/* The following definitions are for OM and NM packets that we cannot yet
59 * generate by code but we just pass on */
60
61// BTS Site Manager, SET ATTRIBUTES
62
63/*
64 Object Class: BTS Site Manager
65 Instance 1: FF
66 Instance 2: FF
67 Instance 3: FF
68SET ATTRIBUTES
69 sAbisExternalTime: 2007/09/08 14:36:11
70 omLAPDRelTimer: 30sec
71 shortLAPDIntTimer: 5sec
72 emergencyTimer1: 10 minutes
73 emergencyTimer2: 0 minutes
74*/
75
76unsigned char msg_1[] =
77{
78 0xD0, 0x00, 0xFF, 0xFF, 0xFF, 0x91, 0x07, 0xD7, 0x09, 0x08, 0x0E, 0x24,
79 0x0B, 0xCE, 0x02, 0x00, 0x1E, 0xE8, 0x01, 0x05, 0x42, 0x02, 0x00, 0x0A, 0x44,
80 0x02, 0x00, 0x00
81};
82
83// BTS, SET BTS ATTRIBUTES
84
85/*
86 Object Class: BTS
87 BTS relat. Number: 0
88 Instance 2: FF
89 Instance 3: FF
90SET BTS ATTRIBUTES
91 bsIdentityCode / BSIC:
92 PLMN_colour_code: 7h
93 BS_colour_code: 7h
94 BTS Air Timer T3105: 4 ,unit 10 ms
95 btsIsHopping: FALSE
96 periodCCCHLoadIndication: 255sec
97 thresholdCCCHLoadIndication: 100%
98 cellAllocationNumber: 00h = GSM 900
99 enableInterferenceClass: 00h = Disabled
100 fACCHQual: 6 (FACCH stealing flags minus 1)
101 intaveParameter: 31 SACCH multiframes
102 interferenceLevelBoundaries:
103 Interference Boundary 1: 0Ah
104 Interference Boundary 2: 0Fh
105 Interference Boundary 3: 14h
106 Interference Boundary 4: 19h
107 Interference Boundary 5: 1Eh
108 mSTxPwrMax: 11
109 GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
110 DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
111 PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
112 30=33dBm, 31=32dBm
113 ny1:
114 Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
115 powerOutputThresholds:
116 Out Power Fault Threshold: -10 dB
117 Red Out Power Threshold: - 6 dB
118 Excessive Out Power Threshold: 5 dB
119 rACHBusyThreshold: -127 dBm
120 rACHLoadAveragingSlots: 250 ,number of RACH burst periods
121 rfResourceIndicationPeriod: 125 SACCH multiframes
122 T200:
123 SDCCH: 044 in 5 ms
124 FACCH/Full rate: 031 in 5 ms
125 FACCH/Half rate: 041 in 5 ms
126 SACCH with TCH SAPI0: 090 in 10 ms
127 SACCH with SDCCH: 090 in 10 ms
128 SDCCH with SAPI3: 090 in 5 ms
129 SACCH with TCH SAPI3: 135 in 10 ms
130 tSync: 9000 units of 10 msec
131 tTrau: 9000 units of 10 msec
132 enableUmLoopTest: 00h = disabled
133 enableExcessiveDistance: 00h = Disabled
134 excessiveDistance: 64km
135 hoppingMode: 00h = baseband hopping
136 cellType: 00h = Standard Cell
137 BCCH ARFCN / bCCHFrequency: 1
138*/
139
140unsigned char msg_2[] =
141{
142 0x41, 0x01, 0x00, 0xFF, 0xFF, 0x09, 0x3F, 0x0A, 0x04, 0x61, 0x00, 0x0B,
143 0xFF, 0x0C, 0x64, 0x62, 0x00, 0x66, 0x00, 0x6E, 0x06, 0x18, 0x1F, 0x19,
144 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B, 0x0B, 0x23, 0x14, 0x28, 0x00, 0x04,
145 0x03, 0x2A, 0x7F, 0x2B, 0x00, 0xFA, 0x8F, 0x7D, 0x33, 0x2C, 0x1F, 0x29,
146 0x5A, 0x5A, 0x5A, 0x87, 0x94, 0x23, 0x28, 0x95, 0x23, 0x28, 0x35, 0x01,
147 0x00, 0x46, 0x01, 0x00, 0x58, 0x01, 0x40, 0xC5, 0x01, 0x00, 0xF2, 0x01,
148 0x00, 0x08, 0x00, HARDCODED_ARFCN/*0x01*/,
149};
150
151// Handover Recognition, SET ATTRIBUTES
152
153/*
154Illegal Contents GSM Formatted O&M Msg
155 Object Class: Handover Recognition
156 BTS relat. Number: 0
157 Instance 2: FF
158 Instance 3: FF
159SET ATTRIBUTES
160 enableDelayPowerBudgetHO: 00h = Disabled
161 enableDistanceHO: 00h = Disabled
162 enableInternalInterCellHandover: 00h = Disabled
163 enableInternalIntraCellHandover: 00h = Disabled
164 enablePowerBudgetHO: 00h = Disabled
165 enableRXLEVHO: 00h = Disabled
166 enableRXQUALHO: 00h = Disabled
167 hoAveragingDistance: 8 SACCH multiframes
168 hoAveragingLev:
169 A_LEV_HO: 8 SACCH multiframes
170 W_LEV_HO: 1 SACCH multiframes
171 hoAveragingPowerBudget: 16 SACCH multiframes
172 hoAveragingQual:
173 A_QUAL_HO: 8 SACCH multiframes
174 W_QUAL_HO: 2 SACCH multiframes
175 hoLowerThresholdLevDL: (10 - 110) dBm
176 hoLowerThresholdLevUL: (5 - 110) dBm
177 hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
178 hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
179 hoThresholdLevDLintra : (20 - 110) dBm
180 hoThresholdLevULintra: (20 - 110) dBm
181 hoThresholdMsRangeMax: 20 km
182 nCell: 06h
183 timerHORequest: 3 ,unit 2 SACCH multiframes
184*/
185
186unsigned char msg_3[] =
187{
188 0xD0, 0xA1, 0x00, 0xFF, 0xFF, 0xD0, 0x00, 0x64, 0x00, 0x67, 0x00, 0x68,
189 0x00, 0x6A, 0x00, 0x6C, 0x00, 0x6D, 0x00, 0x6F, 0x08, 0x70, 0x08, 0x01,
190 0x71, 0x10, 0x10, 0x10, 0x72, 0x08, 0x02, 0x73, 0x0A, 0x74, 0x05, 0x75,
191 0x06, 0x76, 0x06, 0x78, 0x14, 0x79, 0x14, 0x7A, 0x14, 0x7D, 0x06, 0x92,
192 0x03, 0x20, 0x01, 0x00, 0x45, 0x01, 0x00, 0x48, 0x01, 0x00, 0x5A, 0x01,
193 0x00, 0x5B, 0x01, 0x05, 0x5E, 0x01, 0x1A, 0x5F, 0x01, 0x20, 0x9D, 0x01,
194 0x00, 0x47, 0x01, 0x00, 0x5C, 0x01, 0x64, 0x5D, 0x01, 0x1E, 0x97, 0x01,
195 0x20, 0xF7, 0x01, 0x3C,
196};
197
198// Power Control, SET ATTRIBUTES
199
200/*
201 Object Class: Power Control
202 BTS relat. Number: 0
203 Instance 2: FF
204 Instance 3: FF
205SET ATTRIBUTES
206 enableMsPowerControl: 00h = Disabled
207 enablePowerControlRLFW: 00h = Disabled
208 pcAveragingLev:
209 A_LEV_PC: 4 SACCH multiframes
210 W_LEV_PC: 1 SACCH multiframes
211 pcAveragingQual:
212 A_QUAL_PC: 4 SACCH multiframes
213 W_QUAL_PC: 2 SACCH multiframes
214 pcLowerThresholdLevDL: 0Fh
215 pcLowerThresholdLevUL: 0Ah
216 pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
217 pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
218 pcRLFThreshold: 0Ch
219 pcUpperThresholdLevDL: 14h
220 pcUpperThresholdLevUL: 0Fh
221 pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
222 pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
223 powerConfirm: 2 ,unit 2 SACCH multiframes
224 powerControlInterval: 2 ,unit 2 SACCH multiframes
225 powerIncrStepSize: 02h = 4 dB
226 powerRedStepSize: 01h = 2 dB
227 radioLinkTimeoutBs: 64 SACCH multiframes
228 enableBSPowerControl: 00h = disabled
229*/
230
231unsigned char msg_4[] =
232{
233 0xD0, 0xA2, 0x00, 0xFF, 0xFF, 0x69, 0x00, 0x6B, 0x00, 0x7E, 0x04, 0x01,
234 0x7F, 0x04, 0x02, 0x80, 0x0F, 0x81, 0x0A, 0x82, 0x05, 0x83, 0x05, 0x84,
235 0x0C, 0x85, 0x14, 0x86, 0x0F, 0x87, 0x04, 0x88, 0x04, 0x89, 0x02, 0x8A,
236 0x02, 0x8B, 0x02, 0x8C, 0x01, 0x8D, 0x40, 0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
237};
238
239
240// Transceiver, SET TRX ATTRIBUTES (TRX 0)
241
242/*
243 Object Class: Transceiver
244 BTS relat. Number: 0
245 Tranceiver number: 0
246 Instance 3: FF
247SET TRX ATTRIBUTES
248 aRFCNList (HEX): 0001
249 txPwrMaxReduction: 00h = 0dB
250 radioMeasGran: 254 SACCH multiframes
251 radioMeasRep: 01h = enabled
252 memberOfEmergencyConfig: 01h = TRUE
253 trxArea: 00h = TRX doesn't belong to a concentric cell
254*/
255
256unsigned char msg_6[] =
257{
258 0x44, 0x02, 0x00, 0x00, 0xFF, 0x05, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/, 0x2D,
259 0x00, 0xDC, 0x01, 0xFE, 0xDD, 0x01, 0x01, 0x9B, 0x01, 0x01, 0x9F, 0x01, 0x00,
260};
261
262
263static void bootstrap_om(struct gsm_bts *bts)
264{
265 struct gsm_bts_trx *trx = &bts->trx[0];
266
Harald Weltead384642008-12-26 10:20:07 +0000267 fprintf(stdout, "bootstrapping OML\n");
268
Harald Welte52b1f982008-12-23 20:25:15 +0000269 /* stop sending event reports */
270 abis_nm_event_reports(bts, 0);
271
272 /* begin DB transmission */
273 abis_nm_db_transmission(bts, 1);
274
Harald Welte702d8702008-12-26 20:25:35 +0000275 /* end DB transmission */
276 abis_nm_db_transmission(bts, 0);
277
278 /* Reset BTS Site manager resource */
279 abis_nm_reset_resource(bts);
280
281 /* begin DB transmission */
282 abis_nm_db_transmission(bts, 1);
283
Harald Welte52b1f982008-12-23 20:25:15 +0000284 abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
285 abis_nm_raw_msg(bts, sizeof(msg_2), msg_2); /* set BTS attr */
286 abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
287 abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
288
289 /* Connect signalling of bts0/trx0 to e1_0/ts1/64kbps */
290 abis_nm_conn_terr_sign(trx, 0, 1, 0xff);
291 abis_nm_raw_msg(bts, sizeof(msg_6), msg_6); /* SET TRX ATTRIBUTES */
292
293 /* Use TEI 1 for signalling */
294 abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x01);
295 abis_nm_set_channel_attr(&trx->ts[0], NM_CHANC_SDCCH_CBCH);
296#if 0
297 /* TRX 1 */
298 abis_nm_conn_terr_sign(&bts->trx[1], 0, 1, 0xff);
299 /* FIXME: TRX ATTRIBUTE */
300 abis_nm_establish_tei(bts, 0, 0, 1, 0xff, 0x02);
301#endif
302
303 /* SET CHANNEL ATTRIBUTE TS1 */
304 abis_nm_set_channel_attr(&trx->ts[1], 0x09);
305 /* Connect traffic of bts0/trx0/ts1 to e1_0/ts2/b */
306 abis_nm_conn_terr_traf(&trx->ts[1], 0, 2, 1);
307
308 /* SET CHANNEL ATTRIBUTE TS2 */
309 abis_nm_set_channel_attr(&trx->ts[2], 0x09);
310 /* Connect traffic of bts0/trx0/ts2 to e1_0/ts2/c */
311 abis_nm_conn_terr_traf(&trx->ts[2], 0, 2, 2);
312
313 /* SET CHANNEL ATTRIBUTE TS3 */
314 abis_nm_set_channel_attr(&trx->ts[3], 0x09);
315 /* Connect traffic of bts0/trx0/ts3 to e1_0/ts2/d */
316 abis_nm_conn_terr_traf(&trx->ts[3], 0, 2, 3);
317
318 /* SET CHANNEL ATTRIBUTE TS4 */
319 abis_nm_set_channel_attr(&trx->ts[4], 0x09);
320 /* Connect traffic of bts0/trx0/ts4 to e1_0/ts3/a */
321 abis_nm_conn_terr_traf(&trx->ts[4], 0, 3, 0);
322
323 /* SET CHANNEL ATTRIBUTE TS5 */
324 abis_nm_set_channel_attr(&trx->ts[5], 0x09);
325 /* Connect traffic of bts0/trx0/ts5 to e1_0/ts3/b */
326 abis_nm_conn_terr_traf(&trx->ts[5], 0, 3, 1);
327
328 /* SET CHANNEL ATTRIBUTE TS6 */
329 abis_nm_set_channel_attr(&trx->ts[6], 0x09);
330 /* Connect traffic of bts0/trx0/ts6 to e1_0/ts3/c */
331 abis_nm_conn_terr_traf(&trx->ts[6], 0, 3, 2);
332
333 /* SET CHANNEL ATTRIBUTE TS7 */
334 abis_nm_set_channel_attr(&trx->ts[7], 0x09);
335 /* Connect traffic of bts0/trx0/ts7 to e1_0/ts3/d */
336 abis_nm_conn_terr_traf(&trx->ts[7], 0, 3, 3);
337
338 /* end DB transmission */
339 abis_nm_db_transmission(bts, 0);
340
341 /* Reset BTS Site manager resource */
342 abis_nm_reset_resource(bts);
343
344 /* restart sending event reports */
345 abis_nm_event_reports(bts, 1);
346}
347
348
349
350struct bcch_info {
351 u_int8_t type;
352 u_int8_t len;
353 const u_int8_t *data;
354};
355
356/*
357SYSTEM INFORMATION TYPE 1
358 Cell channel description
359 Format-ID bit map 0
360 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
361 RACH Control Parameters
362 maximum 7 retransmissions
363 8 slots used to spread transmission
364 cell not barred for access
365 call reestablishment not allowed
366 Access Control Class = 0000
367*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000368static u_int8_t si1[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000369 /* header */0x55, 0x06, 0x19,
370 /* ccdesc */0x04 /*0x00*/, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*0x01*/,
372 /* rach */0xD5, 0x00, 0x00,
373 /* s1 reset*/0x2B
Harald Welte52b1f982008-12-23 20:25:15 +0000374};
375
376/*
377 SYSTEM INFORMATION TYPE 2
378 Neighbour Cells Description
379 EXT-IND: Carries the complete BA
380 BA-IND = 0
381 Format-ID bit map 0
382 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
383 NCC permitted (NCC) = FF
384 RACH Control Parameters
385 maximum 7 retransmissions
386 8 slots used to spread transmission
387 cell not barred for access
388 call reestablishment not allowed
389 Access Control Class = 0000
390*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000391static u_int8_t si2[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000392 /* header */0x59, 0x06, 0x1A,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 /* ncc */0xFF,
396 /* rach*/0xD5, 0x00, 0x00
Harald Welte52b1f982008-12-23 20:25:15 +0000397};
398
399/*
400SYSTEM INFORMATION TYPE 3
401 Cell identity = 00001 (1h)
402 Location area identification
403 Mobile Country Code (MCC): 001
404 Mobile Network Code (MNC): 01
405 Location Area Code (LAC): 00001 (1h)
406 Control Channel Description
407 Attach-detach: MSs in the cell are not allowed to apply IMSI attach /detach
408 0 blocks reserved for access grant
409 1 channel used for CCCH, with SDCCH
410 5 multiframes period for PAGING REQUEST
411 Time-out T3212 = 0
412 Cell Options BCCH
413 Power control indicator: not set
414 MSs shall not use uplink DTX
415 Radio link timeout = 36
416 Cell Selection Parameters
417 Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
Harald Welte3b2ec422008-12-29 04:11:14 +0000418 max.TX power level MS may use for CCH = 2 <- according to GSM05.05 39dBm (max)
Harald Welte52b1f982008-12-23 20:25:15 +0000419 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
420 Half rate support (NECI): New establishment causes are not supported
421 min.RX signal level for MS = 0
422 RACH Control Parameters
423 maximum 7 retransmissions
424 8 slots used to spread transmission
425 cell not barred for access
426 call reestablishment not allowed
427 Access Control Class = 0000
428 SI 3 Rest Octets
429 Cell Bar Qualify (CBQ): 0
430 Cell Reselect Offset = 0 dB
431 Temporary Offset = 0 dB
432 Penalty Time = 20 s
433 System Information 2ter Indicator (2TI): 0 = not available
434 Early Classmark Sending Control (ECSC): 0 = forbidden
435 Scheduling Information is not sent in SYSTEM INFORMATION TYPE 9 on the BCCH
436*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000437static u_int8_t si3[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000438 /* header */0x49, 0x06, 0x1B,
439 /* cell */0x00, 0x01,
440 /* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
441 /* desc */0x01, 0x03, 0x00,
442 /* option*/0x28,
443 /* selection*/0x62, 0x00,
444 /* rach */0xD5, 0x00, 0x00,
445 /* reset*/0x80, 0x00, 0x00, 0x2B
Harald Welte52b1f982008-12-23 20:25:15 +0000446};
447
448/*
449SYSTEM INFORMATION TYPE 4
450 Location area identification
451 Mobile Country Code (MCC): 001
452 Mobile Network Code (MNC): 01
453 Location Area Code (LAC): 00001 (1h)
454 Cell Selection Parameters
455 Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
456 max.TX power level MS may use for CCH = 2
457 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
458 Half rate support (NECI): New establishment causes are not supported
459 min.RX signal level for MS = 0
460 RACH Control Parameters
461 maximum 7 retransmissions
462 8 slots used to spread transmission
463 cell not barred for access
464 call reestablishment not allowed
465 Access Control Class = 0000
466 Channel Description
467 Type = SDCCH/4[2]
468 Timeslot Number: 0
469 Training Sequence Code: 7h
470 ARFCN: 1
471 SI Rest Octets
472 Cell Bar Qualify (CBQ): 0
473 Cell Reselect Offset = 0 dB
474 Temporary Offset = 0 dB
475 Penalty Time = 20 s
476*/
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000477static u_int8_t si4[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000478 /* header */0x41, 0x06, 0x1C,
479 /* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
480 /* sel */0x62, 0x00,
481 /* rach*/0xD5, 0x00, 0x00,
482 /* var */0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/, 0x80, 0x00, 0x00,
Harald Welte52b1f982008-12-23 20:25:15 +0000483 0x2B, 0x2B, 0x2B
484};
485
486/*
487 SYSTEM INFORMATION TYPE 5
488 Neighbour Cells Description
489 EXT-IND: Carries the complete BA
490 BA-IND = 0
491 Format-ID bit map 0
492 CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
493*/
494
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000495static u_int8_t si5[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000496 /* header without l2 len*/0x06, 0x1D,
497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Harald Welte52b1f982008-12-23 20:25:15 +0000499};
500
501// SYSTEM INFORMATION TYPE 6
502
503/*
504SACCH FILLING
505 System Info Type: SYSTEM INFORMATION 6
506 L3 Information (Hex): 06 1E 00 01 xx xx 10 00 01 28 FF
507
508SYSTEM INFORMATION TYPE 6
509 Cell identity = 00001 (1h)
510 Location area identification
511 Mobile Country Code (MCC): 001
512 Mobile Network Code (MNC): 01
513 Location Area Code (LAC): 00001 (1h)
514 Cell Options SACCH
515 Power control indicator: not set
516 MSs shall not use uplink DTX on a TCH-F. MS shall not use uplink DTX on TCH-H.
517 Radio link timeout = 36
518 NCC permitted (NCC) = FF
519*/
520
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000521static u_int8_t si6[] = {
Holger Freyther4d505472008-12-28 16:32:42 +0000522 /* header */0x06, 0x1E,
523 /* cell id*/ 0x00, 0x01,
524 /* lai */ 0x00, 0xF1, 0x10, 0x00, 0x01,
525 /* options */ 0x28,
526 /* ncc */ 0xFF,
Harald Welte52b1f982008-12-23 20:25:15 +0000527};
528
529
530
531static const struct bcch_info bcch_infos[] = {
532 {
533 .type = RSL_SYSTEM_INFO_1,
534 .len = sizeof(si1),
535 .data = si1,
536 }, {
537 .type = RSL_SYSTEM_INFO_2,
538 .len = sizeof(si2),
539 .data = si2,
540 }, {
541 .type = RSL_SYSTEM_INFO_3,
542 .len = sizeof(si3),
543 .data = si3,
544 }, {
545 .type = RSL_SYSTEM_INFO_4,
546 .len = sizeof(si4),
547 .data = si4,
548 },
549};
550
Holger Freyther24287b62008-12-28 16:32:41 +0000551static_assert(sizeof(si1) == sizeof(struct gsm48_system_information_type_1), type1)
552static_assert(sizeof(si2) == sizeof(struct gsm48_system_information_type_2), type2)
553static_assert(sizeof(si3) == sizeof(struct gsm48_system_information_type_3), type3)
554static_assert(sizeof(si4) >= sizeof(struct gsm48_system_information_type_4), type4)
Harald Welte104604e2008-12-28 16:36:11 +0000555static_assert(sizeof(si5) == sizeof(struct gsm48_system_information_type_5), type5)
556static_assert(sizeof(si6) >= sizeof(struct gsm48_system_information_type_6), type6)
Holger Freyther24287b62008-12-28 16:32:41 +0000557
Harald Welte52b1f982008-12-23 20:25:15 +0000558/* set all system information types */
559static int set_system_infos(struct gsm_bts *bts)
560{
561 int i;
562
563 for (i = 0; i < ARRAY_SIZE(bcch_infos); i++) {
564 rsl_bcch_info(bts, bcch_infos[i].type,
565 bcch_infos[i].data,
566 bcch_infos[i].len);
567 }
568 rsl_sacch_filling(bts, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
569 rsl_sacch_filling(bts, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
Harald Weltead384642008-12-26 10:20:07 +0000570
571 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000572}
573
574static void activate_traffic_channels(struct gsm_bts_trx *trx)
575{
576 int i;
577
578 /* channel 0 is CCCH */
579 for (i = 1; i < 8; i++)
580 rsl_chan_activate_tch_f(&trx->ts[i]);
581}
582
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000583/*
584 * Patch the various SYSTEM INFORMATION tables to update
585 * the LAI
586 */
587static void patch_tables(struct gsm_bts *bts)
588{
589 /* covert the raw packet to the struct */
590 struct gsm48_system_information_type_3 *type_3 =
591 (struct gsm48_system_information_type_3*)&si3;
592 struct gsm48_system_information_type_4 *type_4 =
593 (struct gsm48_system_information_type_4*)&si4;
594 struct gsm48_system_information_type_6 *type_6 =
595 (struct gsm48_system_information_type_6*)&si6;
Harald Welteb84e2f42008-12-28 23:42:04 +0000596 struct gsm48_loc_area_id lai;
597
598 gsm0408_generate_lai(&lai, bts->network->country_code,
599 bts->network->network_code, bts->location_area_code);
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000600
601 /* assign the MCC and MNC */
Harald Welteb84e2f42008-12-28 23:42:04 +0000602 type_3->lai = lai;
603 type_4->lai = lai;
604 type_6->lai = lai;
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000605}
606
607
Harald Weltead384642008-12-26 10:20:07 +0000608static void bootstrap_rsl(struct gsm_bts *bts)
Harald Welte52b1f982008-12-23 20:25:15 +0000609{
Harald Welteb84e2f42008-12-28 23:42:04 +0000610 fprintf(stdout, "bootstrapping RSL MCC=%u MNC=%u\n", MCC, MNC);
Holger Freytherb9ddfd02008-12-28 16:32:45 +0000611 patch_tables(bts);
Harald Welte52b1f982008-12-23 20:25:15 +0000612 set_system_infos(bts);
613
614 /* FIXME: defer this until the channels are used */
Harald Welte702d8702008-12-26 20:25:35 +0000615 //activate_traffic_channels(&bts->trx[0]);
Harald Welte52b1f982008-12-23 20:25:15 +0000616}
617
Harald Weltead384642008-12-26 10:20:07 +0000618static void mi_cb(int event, struct gsm_bts *bts)
619{
620 switch (event) {
621 case EVT_E1_OML_UP:
622 bootstrap_om(bts);
623 break;
624 case EVT_E1_RSL_UP:
625 bootstrap_rsl(bts);
626 break;
627 default:
628 /* FIXME: deal with TEI or L1 link loss */
629 break;
630 }
631}
632
633static int bootstrap_network(void)
Harald Welte52b1f982008-12-23 20:25:15 +0000634{
635 struct gsm_bts *bts;
636
637 /* initialize our data structures */
Holger Freytherefde7fb2008-12-28 14:14:56 +0000638 gsmnet = gsm_network_init(1, MCC, MNC);
Harald Weltead384642008-12-26 10:20:07 +0000639 if (!gsmnet)
640 return -ENOMEM;
641
Harald Welte52b1f982008-12-23 20:25:15 +0000642 bts = &gsmnet->bts[0];
643 bts->location_area_code = 1;
644 bts->trx[0].arfcn = HARDCODED_ARFCN;
Holger Freyther07cc8d82008-12-29 06:23:46 +0000645 gsmnet->update_request_accepted = bsc_hack_update_request_accepted;
Holger Freyther3186bf22008-12-29 06:23:49 +0000646 gsmnet->channel_allocated = bsc_hack_channel_allocated;
Holger Freyther88ea8322008-12-29 06:23:52 +0000647 gsmnet->channel_response = bsc_hack_channel_response;
Harald Welte52b1f982008-12-23 20:25:15 +0000648
Harald Weltead384642008-12-26 10:20:07 +0000649 if (mi_setup(bts, 0, mi_cb) < 0)
650 return -EIO;
651
652 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000653}
Harald Weltef6b7a902008-12-26 00:05:11 +0000654
Holger Freytherb332f612008-12-27 12:46:51 +0000655static void print_usage()
656{
657 printf("Usage: bsc_hack\n");
658}
659
660static void print_help()
661{
662 printf(" Some useful help...\n");
663 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
Holger Freytherefde7fb2008-12-28 14:14:56 +0000664 printf(" -s --disable-color\n");
665 printf(" -n --network-code number(MNC) \n");
666 printf(" -c --country-code number (MCC) \n");
Holger Freytherbde36102008-12-28 22:51:39 +0000667 printf(" -l --database db-name The database to use\n");
Holger Freytherb332f612008-12-27 12:46:51 +0000668 printf(" -h --help this text\n");
669}
670
671static void handle_options(int argc, char** argv)
672{
673 while (1) {
674 int option_index = 0, c;
675 static struct option long_options[] = {
676 {"help", 0, 0, 'h'},
677 {"debug", 1, 0, 'd'},
Holger Freytherefde7fb2008-12-28 14:14:56 +0000678 {"disable-color", 0, 0, 's'},
679 {"network-code", 1, 0, 'n'},
680 {"country-code", 1, 0, 'c'},
Holger Freytherbde36102008-12-28 22:51:39 +0000681 {"database", 1, 0, 'l'},
Holger Freytherb332f612008-12-27 12:46:51 +0000682 {0, 0, 0, 0}
683 };
684
Holger Freyther33a61842008-12-28 16:57:19 +0000685 c = getopt_long(argc, argv, "hc:n:d:s",
Holger Freytherb332f612008-12-27 12:46:51 +0000686 long_options, &option_index);
687 if (c == -1)
688 break;
689
690 switch (c) {
691 case 'h':
692 print_usage();
693 print_help();
694 exit(0);
Holger Freytherefde7fb2008-12-28 14:14:56 +0000695 case 's':
Holger Freytherb332f612008-12-27 12:46:51 +0000696 debug_use_color(0);
697 break;
698 case 'd':
699 debug_parse_category_mask(optarg);
700 break;
Holger Freytherefde7fb2008-12-28 14:14:56 +0000701 case 'n':
702 MNC = atoi(optarg);
703 break;
704 case 'c':
705 MCC = atoi(optarg);
706 break;
Holger Freytherbde36102008-12-28 22:51:39 +0000707 case 'l':
708 database_name = strdup(optarg);
709 break;
Holger Freytherb332f612008-12-27 12:46:51 +0000710 default:
711 /* ignore */
712 break;
713 }
714 }
715}
716
Harald Welte255539c2008-12-28 02:26:27 +0000717static struct timer_list pag_timer;
718
719/* handles uppercase decimal and hexadecimal */
720static u_int8_t char2bcd(char c)
721{
722 if (c <= '9')
723 return c - '0';
724 else
725 return c - 'A';
726}
727
728static int string_to_mi(u_int8_t *mi, const char *string,
729 u_int8_t type)
730{
731 u_int8_t *cur = mi+3;
732
733 mi[0] = GSM48_IE_MOBILE_ID;
734 //mi[1] = TMSI_LEN;
735 mi[2] = type & GSM_MI_TYPE_MASK;
736
737 if (strlen(string) & 0x01)
738 mi[2] |= char2bcd(*string++) << 4;
739 else
740 mi[2] |= 0xf0;
741
742 while (*string && *(string+1))
743 *cur++ = char2bcd(*string++) | (char2bcd(*string++) << 4);
744
745 mi[1] = cur - mi;
746
747 return cur - mi;
748}
749
Holger Freyther07cc8d82008-12-29 06:23:46 +0000750/*
751 * Stations that registered and that we need to page
752 */
753struct pending_registered_station {
754 struct llist_head entry;
Harald Welte255539c2008-12-28 02:26:27 +0000755
Holger Freyther07cc8d82008-12-29 06:23:46 +0000756 /* the tmsi of the subscriber */
757 u_int32_t tmsi;
758 int last_page_group;
759};
760
761static LLIST_HEAD(pending_stations);
762
763static void pag_timer_cb(void *data);
764static struct timer_list pag_timer = {
765 .cb = pag_timer_cb,
766};
767
768/* page the tmsi and wait for the channel request */
769static void pag_timer_cb(void *data)
Harald Welte255539c2008-12-28 02:26:27 +0000770{
771 struct gsm_bts *bts = &gsmnet->bts[0];
Holger Freyther07cc8d82008-12-29 06:23:46 +0000772 struct pending_registered_station *pending_station;
Harald Welte255539c2008-12-28 02:26:27 +0000773 u_int8_t mi[128];
Holger Freyther07cc8d82008-12-29 06:23:46 +0000774 unsigned int mi_len;
Harald Welte255539c2008-12-28 02:26:27 +0000775
Holger Freyther07cc8d82008-12-29 06:23:46 +0000776 if (llist_empty(&pending_stations)) {
777 DEBUGP(DPAG, "pag_timer_cb but no pending mobile stations\n");
Harald Welte255539c2008-12-28 02:26:27 +0000778 return;
Holger Freyther07cc8d82008-12-29 06:23:46 +0000779 }
Harald Welte255539c2008-12-28 02:26:27 +0000780
Holger Freyther07cc8d82008-12-29 06:23:46 +0000781 /* get the station to page */
782 pending_station = (struct pending_registered_station*) pending_stations.next;
783 mi_len = generate_mid_from_tmsi(mi, pending_station->tmsi);
784 rsl_paging_cmd(bts, pending_station->last_page_group, mi_len, mi, RSL_CHANNEED_TCH_F);
Harald Welte255539c2008-12-28 02:26:27 +0000785
Holger Freyther07cc8d82008-12-29 06:23:46 +0000786 /* which group to page next */
787 pending_station->last_page_group = (pending_station->last_page_group+1) % 12;
788 schedule_timer(&pag_timer, 1, 0);
789}
Harald Welte255539c2008-12-28 02:26:27 +0000790
Holger Freyther07cc8d82008-12-29 06:23:46 +0000791/*
792 * initiate the a page command for the given
793 * station and retry until we get a channel request
794 */
795static void station_timer_cb(void *data)
796{
797 DEBUGP(DPAG, "Initiating paging of a channel\n");
798 pag_timer_cb(0);
799}
Harald Welte255539c2008-12-28 02:26:27 +0000800
Holger Freyther07cc8d82008-12-29 06:23:46 +0000801static struct timer_list station_timer = {
802 .cb = station_timer_cb,
803};
804
805/*
806 * schedule work
807 */
808static void bsc_hack_update_request_accepted(struct gsm_bts *bts, u_int32_t tmsi)
809{
810 struct pending_registered_station *station =
811 (struct pending_registered_station*)malloc(sizeof(*station));
812 station->tmsi = tmsi;
813 station->last_page_group = 0;
814 llist_add_tail(&station->entry, &pending_stations);
815
816 if (!timer_pending(&station_timer))
817 schedule_timer(&station_timer, 1, 0);
Harald Welte255539c2008-12-28 02:26:27 +0000818}
819
Holger Freyther3186bf22008-12-29 06:23:49 +0000820static void bsc_hack_channel_allocated(struct gsm_lchan *chan,
821 enum gsm_chreq_reason_t chreq_reason)
822{
823 struct pending_registered_station *station;
824 if (chreq_reason != GSM_CHREQ_REASON_PAG)
825 return;
826
827 if (llist_empty(&pending_stations)) {
828 DEBUGP(DPAG, "Channel allocated for pag but not waitin for it\n");
829 return;
830 }
831
832 station = (struct pending_registered_station*) pending_stations.next;
833
834 DEBUGP(DPAG, "CHAN RQD due PAG %d on %d for %u\n", chan->type, chan->nr, station->tmsi);
835
836 /* allocate some token in the chan for us */
837 chan->user_data = (void*)station->tmsi;
838 del_timer(&pag_timer);
839}
840
Holger Freyther88ea8322008-12-29 06:23:52 +0000841static void bsc_hack_channel_response(struct gsm_lchan *lchan, int ack)
Holger Freyther24893de2008-12-29 06:23:51 +0000842{
843 struct pending_registered_station *station;
844 if (llist_empty(&pending_stations)) {
845 DEBUGP(DPAG, "Channel nacked but nothing pending\n");
846 return;
847 }
848
849 station = (struct pending_registered_station*) pending_stations.next;
850 if (station->tmsi != (u_int32_t)lchan->user_data) {
851 DEBUGP(DPAG, "Hmmm the channel is not allocated by the"
852 "station we wanted channel: %u us:%u\n",
853 (u_int32_t)(lchan->user_data), station->tmsi);
854 return;
855 }
856
Holger Freyther88ea8322008-12-29 06:23:52 +0000857 if (ack) {
858 DEBUGP(DPAG, "We have probably paged a channel for tmsi: %u on %d\n",
859 station->tmsi, lchan->nr);
Holger Freyther24893de2008-12-29 06:23:51 +0000860
Holger Freyther88ea8322008-12-29 06:23:52 +0000861 llist_del(&station->entry);
862 free(station);
Holger Freytherabade7a2008-12-29 06:42:15 +0000863
864 /*
865 * start a call
866 */
867 gsm48_cc_tx_setup(lchan);
Holger Freyther88ea8322008-12-29 06:23:52 +0000868 } else {
869 /*
870 * give up and go to the next channel
871 */
872 llist_del(&station->entry);
873 free(station);
874 pag_timer_cb(0);
Holger Freyther24893de2008-12-29 06:23:51 +0000875 }
Holger Freyther24893de2008-12-29 06:23:51 +0000876}
877
Harald Weltef6b7a902008-12-26 00:05:11 +0000878int main(int argc, char **argv)
879{
Holger Freytherb332f612008-12-27 12:46:51 +0000880 /* parse options */
881 handle_options(argc, argv);
882
Holger Freytherbde36102008-12-28 22:51:39 +0000883 if (db_init(database_name)) {
Harald Welte75a983f2008-12-27 21:34:06 +0000884 printf("DB: Failed to init database. Please check the option settings.\n");
885 return 1;
886 }
887 printf("DB: Database initialized.\n");
888
889 if (db_prepare()) {
890 printf("DB: Failed to prepare database.\n");
891 return 1;
892 }
893 printf("DB: Database prepared.\n");
894
Harald Weltef6b7a902008-12-26 00:05:11 +0000895 bootstrap_network();
896
897 while (1) {
898 bsc_select_main();
899 }
900}