summaryrefslogtreecommitdiffstats
path: root/include/osmocom/gsm/gsm0808.h
blob: 373b4341e069ddc4928c950b3ba211f5941a1931 (plain)
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
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*! \defgroup gsm0808 GSM 08.08 / 3GPP TS 48.008 A Interface
 *  @{
 *  \file gsm0808.h */
/*
 * (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
 * (C) 2009,2010 by On-Waves
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#pragma once

#include "tlv.h"
#include <osmocom/gsm/protocol/gsm_08_08.h>
#include <osmocom/gsm/gsm0808_utils.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/core/utils.h>

#define BSSMAP_MSG_SIZE 1024
#define BSSMAP_MSG_HEADROOM 512

struct sockaddr_storage;

struct msgb;
struct gsm0808_cell_id_list2;

struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc,
				   uint16_t cc, int lac, uint16_t _ci)
	OSMO_DEPRECATED("Use gsm0808_create_layer3_2() instead, to not lose leading zeros in the MNC");
struct msgb *gsm0808_create_layer3_aoip(const struct msgb *msg_l3, uint16_t nc,
					uint16_t cc, int lac, uint16_t _ci,
					const struct gsm0808_speech_codec_list *scl)
	OSMO_DEPRECATED("Use gsm0808_create_layer3_2() instead, to not lose leading zeros in the MNC");
struct msgb *gsm0808_create_layer3_2(const struct msgb *msg_l3, const struct osmo_cell_global_id *cell,
				     const struct gsm0808_speech_codec_list *scl);
struct msgb *gsm0808_create_reset(void);
struct msgb *gsm0808_create_reset_ack(void);
struct msgb *gsm0808_create_clear_command(uint8_t cause);
struct msgb *gsm0808_create_clear_command2(uint8_t cause, bool csfb_ind);
struct msgb *gsm0808_create_clear_complete(void);
struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,
				   const uint8_t *cipher_response_mode);
struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause);
struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);
struct msgb *gsm0808_create_classmark_request();
struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
					     const uint8_t *cm3, uint8_t cm3_len);
struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
struct msgb *gsm0808_create_ass(const struct gsm0808_channel_type *ct,
				const uint16_t *cic,
				const struct sockaddr_storage *ss,
				const struct gsm0808_speech_codec_list *scl,
				const uint32_t *ci);
struct msgb *gsm0808_create_ass2(const struct gsm0808_channel_type *ct,
				 const uint16_t *cic,
				 const struct sockaddr_storage *ss,
				 const struct gsm0808_speech_codec_list *scl,
				 const uint32_t *ci,
				 const uint8_t *kc, const struct osmo_lcls *lcls);
struct msgb *gsm0808_create_ass_compl(uint8_t rr_cause, uint8_t chosen_channel,
				      uint8_t encr_alg_id, uint8_t speech_mode,
				      const struct sockaddr_storage *ss,
				      const struct gsm0808_speech_codec *sc,
				      const struct gsm0808_speech_codec_list
				      *scl);
struct msgb *gsm0808_create_ass_compl2(uint8_t rr_cause, uint8_t chosen_channel,
				       uint8_t encr_alg_id, uint8_t speech_mode,
				       const struct sockaddr_storage *ss,
				       const struct gsm0808_speech_codec *sc,
				       const struct gsm0808_speech_codec_list *scl,
				       enum gsm0808_lcls_status lcls_bss_status);
struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
						 uint8_t chosen_channel,
						 uint8_t encr_alg_id,
						 uint8_t speech_mode);
struct msgb *gsm0808_create_ass_fail(uint8_t cause, const uint8_t *rr_cause,
				     const struct gsm0808_speech_codec_list
				     *scl);
struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause);
struct msgb *gsm0808_create_clear_rqst(uint8_t cause);
struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi,
				   const struct gsm0808_cell_id_list2 *cil,
				   const uint8_t *chan_needed);
struct msgb *gsm0808_create_paging(const char *imsi, const uint32_t *tmsi,
				   const struct gsm0808_cell_id_list *cil,
				   const uint8_t *chan_needed)
				   OSMO_DEPRECATED("use gsm0808_create_paging2 instead");
struct msgb *gsm0808_create_lcls_conn_ctrl(enum gsm0808_lcls_config config,
					   enum gsm0808_lcls_control control);
struct msgb *gsm0808_create_lcls_conn_ctrl_ack(enum gsm0808_lcls_status status);
struct msgb *gsm0808_create_lcls_notification(enum gsm0808_lcls_status status, bool break_req);


/*! 3GPP TS 48.008 §3.2.2.5.8 Old BSS to New BSS information */
struct gsm0808_old_bss_to_new_bss_info {
	bool extra_information_present;
	struct {
		bool prec;
		bool lcs;
		bool ue_prob;
	} extra_information;

	bool current_channel_type_2_present;
	struct {
		uint8_t mode;
		uint8_t field;
	} current_channel_type_2;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};

/*! 3GPP TS 48.008 §3.2.1.9 HANDOVER REQUIRED */
struct gsm0808_handover_required {
	uint16_t cause;
	struct gsm0808_cell_id_list2 cil;

	bool current_channel_type_1_present;
	uint8_t current_channel_type_1;

	bool speech_version_used_present;
	enum gsm0808_permitted_speech speech_version_used;

	bool old_bss_to_new_bss_info_present;
	struct gsm0808_old_bss_to_new_bss_info old_bss_to_new_bss_info;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};
struct msgb *gsm0808_create_handover_required(const struct gsm0808_handover_required *params);

/*! 3GPP TS 48.008 §3.2.1.37 HANDOVER REQUIRED REJECT */
struct gsm0808_handover_required_reject {
	uint16_t cause;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};
struct msgb *gsm0808_create_handover_required_reject(const struct gsm0808_handover_required_reject *params);

/*! 3GPP TS 48.008 §3.2.1.8 HANDOVER REQUEST */
struct gsm0808_handover_request {
	struct gsm0808_channel_type channel_type;
	struct gsm0808_encrypt_info encryption_information;
	struct osmo_gsm48_classmark classmark_information;
	struct gsm0808_cell_id cell_identifier_serving;
	struct gsm0808_cell_id cell_identifier_target;
	enum gsm0808_cause cause;

	bool current_channel_type_1_present;
	uint8_t current_channel_type_1;

	enum gsm0808_permitted_speech speech_version_used;

	uint8_t chosen_encryption_algorithm_serving;

	/*! Pass either old_bss_to_new_bss_info or old_bss_to_new_bss_info_raw. */
	bool old_bss_to_new_bss_info_present;
	struct gsm0808_old_bss_to_new_bss_info old_bss_to_new_bss_info;
	/*! To feed the Old BSS to New BSS Information IE unchanged from the Handover Required message without having to
	 * decode it. Pass either old_bss_to_new_bss_info or old_bss_to_new_bss_info_raw. Omit the TL part. */
	const uint8_t *old_bss_to_new_bss_info_raw;
	uint8_t old_bss_to_new_bss_info_raw_len;

	const char *imsi;

	const struct sockaddr_storage *aoip_transport_layer;

	const struct gsm0808_speech_codec_list *codec_list_msc_preferred;

	bool call_id_present;
	uint32_t call_id;

	const uint8_t *global_call_reference;
	uint8_t global_call_reference_len;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*!< always set this to false */
};
struct msgb *gsm0808_create_handover_request(const struct gsm0808_handover_request *params);

struct msgb *gsm0808_create_handover_request_ack(const uint8_t *l3_info, uint8_t l3_info_len,
						 uint8_t chosen_channel, uint8_t chosen_encr_alg,
						 uint8_t chosen_speech_version);

struct gsm0808_handover_request_ack {
	const uint8_t *l3_info;
	uint8_t l3_info_len;

	bool chosen_channel_present;
	uint8_t chosen_channel;

	/*! For A5/N set chosen_encr_alg = N+1, e.g. chosen_encr_alg = 1 means A5/0 (no encryption), 2 means A5/1, 4
	 * means A5/3. Set chosen_encr_alg = 0 to omit the Chosen Encryption Algorithm IE. */
	uint8_t chosen_encr_alg;

	/* chosen_speech_version == 0 omits the IE */
	enum gsm0808_permitted_speech chosen_speech_version;

	bool speech_codec_chosen_present;
	struct gsm0808_speech_codec speech_codec_chosen;

	const struct sockaddr_storage *aoip_transport_layer;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*!< always set this to false */
};
struct msgb *gsm0808_create_handover_request_ack2(const struct gsm0808_handover_request_ack *params);

struct gsm0808_handover_command {
	const uint8_t *l3_info;
	uint8_t l3_info_len;

	struct gsm0808_cell_id cell_identifier;

	const uint8_t *new_bss_to_old_bss_info_raw;
	size_t new_bss_to_old_bss_info_raw_len;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*!< always set this to false */
};
struct msgb *gsm0808_create_handover_command(const struct gsm0808_handover_command *params);

struct msgb *gsm0808_create_handover_detect();
struct msgb *gsm0808_create_handover_succeeded();

struct gsm0808_handover_complete {
	bool rr_cause_present;
	uint8_t rr_cause;

	bool speech_codec_chosen_present;
	struct gsm0808_speech_codec speech_codec_chosen;

	struct gsm0808_speech_codec_list codec_list_bss_supported; /*< omit when .len == 0 */

	bool chosen_encr_alg_present;
	uint8_t chosen_encr_alg;
	
	bool chosen_channel_present;
	uint8_t chosen_channel;

	bool lcls_bss_status_present;
	enum gsm0808_lcls_status lcls_bss_status;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};
struct msgb *gsm0808_create_handover_complete(const struct gsm0808_handover_complete *params);

struct gsm0808_handover_failure {
	uint16_t cause;

	bool rr_cause_present;
	uint8_t rr_cause;

	struct gsm0808_speech_codec_list codec_list_bss_supported; /*< omit when .len == 0 */

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};
struct msgb *gsm0808_create_handover_failure(const struct gsm0808_handover_failure *params);

struct gsm0808_handover_performed {
	uint16_t cause;
	struct gsm0808_cell_id cell_id;

	bool chosen_channel_present;
	uint8_t chosen_channel;

	bool chosen_encr_alg_present;
	uint8_t chosen_encr_alg;

	bool speech_version_chosen_present;
	enum gsm0808_permitted_speech speech_version_chosen;

	bool speech_codec_chosen_present;
	struct gsm0808_speech_codec speech_codec_chosen;

	bool lcls_bss_status_present;
	enum gsm0808_lcls_status lcls_bss_status;

	/* more items are defined in the spec and may be added later */
	bool more_items; /*< always set this to false */
};
struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_performed *params);

struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id);
void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id);

const struct tlv_definition *gsm0808_att_tlvdef(void);

/*! Parse BSSAP TLV structure using \ref tlv_parse */
#define osmo_bssap_tlv_parse(dec, buf, len) tlv_parse(dec, gsm0808_att_tlvdef(), buf, len, 0, 0)
/*! Parse BSSAP TLV structure using \ref tlv_parse2 */
#define osmo_bssap_tlv_parse2(dec, dec_multiples, buf, len) \
	tlv_parse2(dec, dec_multiples, gsm0808_att_tlvdef(), buf, len, 0, 0)

const char *gsm0808_bssmap_name(uint8_t msg_type);
const char *gsm0808_bssap_name(uint8_t msg_type);
const char *gsm0808_cause_name(enum gsm0808_cause cause);
const char *gsm0808_cause_class_name(enum gsm0808_cause_class class);

extern const struct value_string gsm0808_lcls_config_names[];
extern const struct value_string gsm0808_lcls_control_names[];
extern const struct value_string gsm0808_lcls_status_names[];

static inline const char *gsm0808_lcls_config_name(enum gsm0808_lcls_config val) {
	return get_value_string(gsm0808_lcls_config_names, val);
}
static inline const char *gsm0808_lcls_control_name(enum gsm0808_lcls_control val) {
	return get_value_string(gsm0808_lcls_control_names, val);
}
static inline const char *gsm0808_lcls_status_name(enum gsm0808_lcls_status val) {
	return get_value_string(gsm0808_lcls_status_names, val);
}

/*! @} */