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