1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
|
/* Encoding/Decoding routines for GSM System Information messages
* according to 3GPP TS 44.018 Version 12.3.0 Release 12
*
* (C) 2018 Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
* Released under the terms of GNU General Public License, Version 2 or
* (at your option) any later version.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
module GSM_SystemInformation {
import from General_Types all;
import from GSM_Types all;
import from GSM_RR_Types all;
import from GSM_RestOctets all;
import from Osmocom_Types all;
type union ArfcnOrMaio {
uint12_t arfcn,
MaioHsn maio_hsn
} with { variant "" };
/* 24.008 10.5.1.1 */
type uint16_t SysinfoCellIdentity;
/* 44.018 10.5.2.1b */
type octetstring CellChannelDescription with { variant "FIELDLENGTH(16)" };
/* 44.018 10.5.2.3 */
type enumerated CellOptions_DTX {
MS_MAY_USE_UL_DTX ('00'B),
MS_SHALL_USE_UL_DTX ('01'B),
MS_SHALL_NOT_USE_UL_DTX ('10'B)
} with { variant "FIELDLENGTH(2)" };
type record CellOptions {
boolean dn_ind,
boolean pwrc,
CellOptions_DTX dtx,
uint4_t radio_link_tout_div4
} with { variant "" };
/* 44.018 10.5.2.3a */
type record CellOptionsSacch {
BIT1 dtx_ext,
boolean pwrc,
BIT2 dtx,
BIT4 radio_link_timeout
} with { variant "" };
/* 44.018 10.5.2.4 */
type record CellSelectionParameters {
uint3_t cell_resel_hyst_2dB,
uint5_t ms_txpwr_max_cch,
BIT1 acs,
boolean neci,
uint6_t rxlev_access_min
} with { variant "" };
/* 44.018 10.5.2.11 */
type enumerated CtrlChanDesc_CC {
CCHAN_DESC_1CCCH_NOT_COMBINED ('000'B),
CCHAN_DESC_1CCCH_COMBINED ('001'B),
CCHAN_DESC_2CCCH_NOT_COMBINED ('010'B),
CCHAN_DESC_3CCCH_NOT_COMBINED ('100'B),
CCHAN_DESC_4CCCH_NOT_COMBINED ('110'B)
} with { variant "FIELDLENGTH(3)" };
type enumerated CBQ3 {
CBQ3_IU_MODE_NOT_SUPPORTED ('00'B),
CBQ3_IU_MODE_MS_BARRED ('01'B),
CBQ3_IU_MODE_NOT_BARRED ('10'B)
} with { variant "FIELDLENGTH(2)" };
type record ControlChannelDescription {
boolean msc_r99,
boolean att,
uint3_t bs_ag_blks_res,
CtrlChanDesc_CC ccch_conf,
boolean si22ind,
CBQ3 cbq3,
BIT2 spare,
uint3_t bs_pa_mfrms, /* off by 2 */
uint8_t t3212
} with { variant "" };
template ControlChannelDescription t_ControlChannelDescription := { ?, ?, ?, ?, ?, ?, '00'B, ?, ? };
/* 44.018 10.5.2.22 */
type octetstring NeighbourCellDescription with { variant "FIELDLENGTH(16)" };
/* 44.018 10.5.2.22a */
type octetstring NeighbourCellDescription2 with { variant "FIELDLENGTH(16)" };
type bitstring AccessControlClass with { variant "FIELDLENGTH(16), BYTEORDER(last)" };
/* 44.018 10.5.2.29 */
type enumerated RachCtrlPar_MR {
RACH_MAX_RETRANS_1 ('00'B),
RACH_MAX_RETRANS_2 ('01'B),
RACH_MAX_RETRANS_4 ('10'B),
RACH_MAX_RETRANS_7 ('11'B)
} with { variant "FIELDLENGTH(2)" };
type record RachControlParameters {
RachCtrlPar_MR max_retrans,
BIT4 tx_integer,
boolean cell_barr_access,
boolean re_not_allowed,
AccessControlClass acc
} with { variant (acc) "FIELDLENGTH(16)" };
/* 44.018 9.1.31 */
type record SystemInformationType1 {
CellChannelDescription cell_chan_desc,
RachControlParameters rach_control,
RestOctets rest_octets length(0..1)
} with { variant "" };
/* 44.018 9.1.32 */
type record SystemInformationType2 {
NeighbourCellDescription bcch_freq_list,
BIT8 ncc_permitted,
RachControlParameters rach_control
} with { variant "" };
/* 44.018 9.1.33 */
type record SystemInformationType2bis {
NeighbourCellDescription extd_bcch_freq_list,
RachControlParameters rach_control,
RestOctets rest_octets length(0..1)
} with { variant "" };
/* 44.018 9.1.34 */
type record SystemInformationType2ter {
NeighbourCellDescription2 extd_bcch_freq_list,
RestOctets rest_octets length(0..4)
} with { variant "" };
type record SystemInformationType2quater {
SI2quaterRestOctets rest_octets
} with { variant "" };
/* 44.018 9.1.35 */
type record SystemInformationType3 {
SysinfoCellIdentity cell_id,
LocationAreaIdentification lai,
ControlChannelDescription ctrl_chan_desc,
CellOptions cell_options,
CellSelectionParameters cell_sel_par,
RachControlParameters rach_control,
SI3RestOctets rest_octets
} with { variant "" };
template SystemInformationType3 t_SI3 := {
cell_id := ?,
lai := ?,
ctrl_chan_desc := t_ControlChannelDescription,
cell_options := ?,
cell_sel_par := ?,
rach_control := ?,
rest_octets := ?
};
/* 44.018 9.1.36 */
type record SystemInformationType4 {
LocationAreaIdentification lai,
CellSelectionParameters cell_sel_par,
RachControlParameters rach_control,
ChannelDescriptionTV cbch_chan_desc optional,
MobileAllocationTLV cbch_mobile_alloc optional,
SI4RestOctets rest_octets /* see 10.5.2.35 */
} with { variant "TAG(cbch_chan_desc, iei = '64'O; cbch_mobile_alloc, iei = '72'O)" };
/* 44.018 9.1.37 */
type record SystemInformationType5 {
NeighbourCellDescription bcch_freq_list
} with { variant "" };
/* 44.018 9.1.38 */
type record SystemInformationType5bis {
NeighbourCellDescription extd_bcch_freq_list
} with { variant "" };
/* 44.018 9.1.39 */
type record SystemInformationType5ter {
NeighbourCellDescription2 extd_bcch_freq_list
} with { variant "" };
/* 44.018 9.1.40 */
type record SystemInformationType6 {
SysinfoCellIdentity cell_id,
LocationAreaIdentification lai,
CellOptionsSacch cell_options,
BIT8 ncc_permitted,
RestOctets rest_octets length(0..7)
} with { variant "" };
type union SystemInformationUnion {
SystemInformationType1 si1,
SystemInformationType2 si2,
SystemInformationType2bis si2bis,
SystemInformationType2ter si2ter,
SystemInformationType2quater si2quater,
SystemInformationType3 si3,
SystemInformationType4 si4,
SystemInformationType5 si5,
SystemInformationType5bis si5bis,
SystemInformationType5ter si5ter,
SystemInformationType6 si6,
octetstring other
} with { variant "" };
type record SystemInformation {
RrHeader header,
SystemInformationUnion payload
} with { variant (payload) "CROSSTAG(si1, header.message_type = SYSTEM_INFORMATION_TYPE_1;
si2, header.message_type = SYSTEM_INFORMATION_TYPE_2;
si2bis, header.message_type = SYSTEM_INFORMATION_TYPE_2bis;
si2ter, header.message_type = SYSTEM_INFORMATION_TYPE_2ter;
si2quater, header.message_type = SYSTEM_INFORMATION_TYPE_2quater;
si3, header.message_type = SYSTEM_INFORMATION_TYPE_3;
si4, header.message_type = SYSTEM_INFORMATION_TYPE_4;
si5, header.message_type = SYSTEM_INFORMATION_TYPE_5;
si5bis, header.message_type = SYSTEM_INFORMATION_TYPE_5bis;
si5ter, header.message_type = SYSTEM_INFORMATION_TYPE_5ter;
si6, header.message_type = SYSTEM_INFORMATION_TYPE_6;
other, OTHERWISE;
)" };
external function enc_SystemInformationNoPad(in SystemInformation si) return octetstring
with { extension "prototype(convert) encode(RAW)" };
external function dec_SystemInformation(in octetstring stream) return SystemInformation
with { extension "prototype(convert) decode(RAW)" };
/* Due to a buggy nature of TITAN's padding attributes, we have to apply padding manually. */
function enc_SystemInformation(in SystemInformation si) return octetstring
{
var octetstring si_enc := enc_SystemInformationNoPad(si);
/* Resulting message length depends on SI Type */
select (si.header.message_type) {
case (SYSTEM_INFORMATION_TYPE_5,
SYSTEM_INFORMATION_TYPE_5bis,
SYSTEM_INFORMATION_TYPE_5ter) {
/* SACCH: no Rest Octets, return 'as-is' */
return si_enc;
}
case (SYSTEM_INFORMATION_TYPE_6) {
/* SACCH: pad to 19 octets, leave room for L1/LAPDm headers */
return f_pad_oct(si_enc, 19, '2B'O);
}
case else {
/* BCCH: pad to 23 octets */
return f_pad_oct(si_enc, 23, '2B'O);
}
}
}
external function dec_SystemInformationSafeBT(in octetstring stream, out SystemInformation si)
return integer /* Decoding result: successful (0) or unsuccessful (1) */
with { extension "prototype(backtrack) decode(RAW)" };
/* Some types of System Information (mostly the Rest Octets) are not fully implemented,
* so calling the generic dec_SystemInformation() may result in a DTE. This function
* additionally checks RR Protocol Discriminator, and should be used in the most cases. */
function dec_SystemInformationSafe(in octetstring stream, out SystemInformation si)
return integer {
/* Try to decode a given octetstring as System Information */
if (dec_SystemInformationSafeBT(stream, si) != 0) {
log("Failed to decode (RR) System Information: ", stream);
return 1;
}
/* Check the protocol discriminator (we expect RR messages) */
if (si.header.rr_protocol_discriminator != bit2int('0110'B)) {
log("Protocol discriminator is not RR (!= '0110'B): ",
si.header.rr_protocol_discriminator);
return 1;
}
return 0;
}
} with { encode "RAW"; variant "FIELDORDER(msb)" }
|