blob: f06e8b76c05cc76c337f0651b51d8eedce45c06e [file] [log] [blame]
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01001/*
2 * (C) 2012 by Holger Hans Peter Freyther
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <osmocom/gsm/gsm0808.h>
Philipp Maier22401432017-03-24 17:59:26 +010022#include <osmocom/gsm/gsm0808_utils.h>
23#include <osmocom/gsm/protocol/gsm_08_08.h>
Philipp Maier3d48ec02017-03-29 17:37:55 +020024#include <osmocom/gsm/protocol/gsm_08_58.h>
Max969fb2e2018-12-10 11:01:10 +010025#include <osmocom/core/logging.h>
26#include <osmocom/core/application.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010027
28#include <stdio.h>
29#include <stdlib.h>
Philipp Maier22401432017-03-24 17:59:26 +010030#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
Neels Hofmeyr74663d92018-03-23 01:46:42 +010033#include <errno.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010034
Philipp Maier4f4905f2018-11-30 13:36:12 +010035#define EXPECT_ENCODED(hexstr) do { \
36 const char *enc_str = msgb_hexdump(msg); \
37 printf("%s: encoded: %s(rc = %u)\n", __func__, enc_str, rc_enc); \
38 OSMO_ASSERT(strcmp(enc_str, hexstr " ") == 0); \
39 OSMO_ASSERT(rc_enc == msg->len); \
40 } while(0)
41
Vadim Yanitskiycf6ee642018-12-20 05:23:00 +070042#define VERIFY(msg, data, data_len) do { \
43 if (!msgb_eq_l3_data_print(msg, data, data_len)) \
44 abort(); \
45 } while(0)
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010046
Philipp Maierfa896ab2017-03-27 16:55:32 +020047/* Setup a fake codec list for testing */
48static void setup_codec_list(struct gsm0808_speech_codec_list *scl)
49{
50 memset(scl, 0, sizeof(*scl));
51
52 scl->codec[0].pi = true;
53 scl->codec[0].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020054 scl->codec[0].type = GSM0808_SCT_FR3;
Philipp Maierfa896ab2017-03-27 16:55:32 +020055 scl->codec[0].cfg = 0xcdef;
56
57 scl->codec[1].fi = true;
58 scl->codec[1].pt = true;
Philipp Maierbb839662017-06-01 17:11:19 +020059 scl->codec[1].type = GSM0808_SCT_FR2;
Philipp Maierfa896ab2017-03-27 16:55:32 +020060
61 scl->codec[2].fi = true;
62 scl->codec[2].tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +020063 scl->codec[2].type = GSM0808_SCT_CSD;
64 scl->codec[2].cfg = 0xc0;
Philipp Maierfa896ab2017-03-27 16:55:32 +020065
66 scl->len = 3;
67}
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010068
Philipp Maier4f4905f2018-11-30 13:36:12 +010069void test_gsm0808_enc_cause(void)
70{
71 /* NOTE: This must be tested early because many of the following tests
72 * rely on the generation of a proper cause code. */
73
74 uint8_t rc_enc;
75 struct msgb *msg;
76
77 /* Test with a single byte cause code */
78 msg = msgb_alloc(1024, "output buffer");
79 rc_enc = gsm0808_enc_cause(msg, 0x41);
80 EXPECT_ENCODED("04 01 41");
81 msgb_free(msg);
82
83 /* Test with an extended (two byte) cause code */
84 msg = msgb_alloc(1024, "output buffer");
85 rc_enc = gsm0808_enc_cause(msg, 0x8041);
86 EXPECT_ENCODED("04 02 80 41");
87 msgb_free(msg);
88}
89
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010090static void test_create_layer3(void)
91{
92 static const uint8_t res[] = {
93 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
94 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
95 struct msgb *msg, *in_msg;
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +020096 struct osmo_cell_global_id cgi = {
97 .lai = {
98 .plmn = {
99 .mcc = 0x2244,
100 .mnc = 0x1122,
101 },
102 .lac = 0x3366,
103 },
104 .cell_identity = 0x4488,
105 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100106 printf("Testing creating Layer3\n");
107
108 in_msg = msgb_alloc_headroom(512, 128, "foo");
109 in_msg->l3h = in_msg->data;
110 msgb_v_put(in_msg, 0x23);
111
Neels Hofmeyr178bf7a2018-04-20 12:23:45 +0200112 msg = gsm0808_create_layer3_2(in_msg, &cgi, NULL);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100113 VERIFY(msg, res, ARRAY_SIZE(res));
114 msgb_free(msg);
115 msgb_free(in_msg);
116}
117
Philipp Maierfa896ab2017-03-27 16:55:32 +0200118static void test_create_layer3_aoip()
119{
120 static const uint8_t res[] = {
121 0x00, 0x17, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
122 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23,
Philipp Maierbb839662017-06-01 17:11:19 +0200123 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50,
Philipp Maier7e27b142018-03-22 17:26:46 +0100124 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maierbb839662017-06-01 17:11:19 +0200125 GSM0808_SCT_CSD | 0x90, 0xc0
Philipp Maierfa896ab2017-03-27 16:55:32 +0200126 };
Maxfa3b4822018-11-05 14:59:54 +0100127 struct osmo_cell_global_id cgi = {
128 .lai = {
129 .plmn = {
130 .mcc = 0x2244,
131 .mnc = 0x1122,
132 },
133 .lac = 0x3366,
134 },
135 .cell_identity = 0x4488,
136 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200137 struct msgb *msg, *in_msg;
138 struct gsm0808_speech_codec_list sc_list;
139 printf("Testing creating Layer3 (AoIP)\n");
140
141 setup_codec_list(&sc_list);
142
143 in_msg = msgb_alloc_headroom(512, 128, "foo");
144 in_msg->l3h = in_msg->data;
145 msgb_v_put(in_msg, 0x23);
146
Maxfa3b4822018-11-05 14:59:54 +0100147 msg = gsm0808_create_layer3_2(in_msg, &cgi, &sc_list);
148
Philipp Maierfa896ab2017-03-27 16:55:32 +0200149 VERIFY(msg, res, ARRAY_SIZE(res));
150
151 msgb_free(msg);
152 msgb_free(in_msg);
153}
154
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100155static void test_create_reset()
156{
157 static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
158 struct msgb *msg;
159
160 printf("Testing creating Reset\n");
161 msg = gsm0808_create_reset();
162 VERIFY(msg, res, ARRAY_SIZE(res));
163 msgb_free(msg);
164}
165
Philipp Maier15596e22017-04-05 17:55:27 +0200166static void test_create_reset_ack()
167{
168 static const uint8_t res[] = { 0x00, 0x01, 0x31 };
169 struct msgb *msg;
170
171 printf("Testing creating Reset Ack\n");
172 msg = gsm0808_create_reset_ack();
173 VERIFY(msg, res, ARRAY_SIZE(res));
174 msgb_free(msg);
175}
176
177
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100178static void test_create_clear_command()
179{
180 static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
181 struct msgb *msg;
182
183 printf("Testing creating Clear Command\n");
184 msg = gsm0808_create_clear_command(0x23);
185 VERIFY(msg, res, ARRAY_SIZE(res));
186 msgb_free(msg);
187}
188
189static void test_create_clear_complete()
190{
191 static const uint8_t res[] = { 0x00, 0x01, 0x21 };
192 struct msgb *msg;
193
194 printf("Testing creating Clear Complete\n");
195 msg = gsm0808_create_clear_complete();
196 VERIFY(msg, res, ARRAY_SIZE(res));
197 msgb_free(msg);
198}
199
Philipp Maierb478dd32017-03-29 15:50:05 +0200200static void test_create_cipher()
201{
202 static const uint8_t res[] =
203 { 0x00, 0x0c, 0x53, 0x0a, 0x09, 0x03, 0xaa,
204 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42 };
205 static const uint8_t res2[] =
206 { 0x00, 0x0e, 0x53, 0x0a, 0x09, 0x03, 0xaa,
207 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42,
208 GSM0808_IE_CIPHER_RESPONSE_MODE, 0x01 };
209 struct msgb *msg;
210 struct gsm0808_encrypt_info ei;
211 uint8_t include_imeisv;
212
213 memset(&ei, 0, sizeof(ei));
214 ei.perm_algo[0] = GSM0808_ALG_ID_A5_0;
215 ei.perm_algo[1] = GSM0808_ALG_ID_A5_1;
216 ei.perm_algo_len = 2;
217 ei.key[0] = 0xaa;
218 ei.key[1] = 0xbb;
219 ei.key[2] = 0xcc;
220 ei.key[3] = 0xdd;
221 ei.key[4] = 0xee;
222 ei.key[5] = 0xff;
223 ei.key[6] = 0x23;
224 ei.key[7] = 0x42;
225 ei.key_len = 8;
226 include_imeisv = 1;
227
228 printf("Testing creating Chipher Mode Command\n");
229 msg = gsm0808_create_cipher(&ei, NULL);
230 OSMO_ASSERT(msg);
231 VERIFY(msg, res, ARRAY_SIZE(res));
232 msgb_free(msg);
233
234 msg = gsm0808_create_cipher(&ei, &include_imeisv);
235 OSMO_ASSERT(msg);
236 VERIFY(msg, res2, ARRAY_SIZE(res2));
237 msgb_free(msg);
238}
239
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100240static void test_create_cipher_complete()
241{
242 static const uint8_t res1[] = {
243 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
244 static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
245 struct msgb *l3, *msg;
246
247 printf("Testing creating Cipher Complete\n");
248 l3 = msgb_alloc_headroom(512, 128, "l3h");
249 l3->l3h = l3->data;
250 msgb_v_put(l3, 0x23);
251 msgb_v_put(l3, 0x42);
252 msgb_v_put(l3, 0x21);
253
254 /* with l3 data */
255 msg = gsm0808_create_cipher_complete(l3, 4);
256 VERIFY(msg, res1, ARRAY_SIZE(res1));
257 msgb_free(msg);
258
259 /* with l3 data but short */
260 l3->len -= 1;
261 l3->tail -= 1;
262 msg = gsm0808_create_cipher_complete(l3, 4);
263 VERIFY(msg, res2, ARRAY_SIZE(res2));
264 msgb_free(msg);
265
266 /* without l3 data */
267 msg = gsm0808_create_cipher_complete(NULL, 4);
268 VERIFY(msg, res2, ARRAY_SIZE(res2));
269 msgb_free(msg);
270
271
272 msgb_free(l3);
273}
274
Maxed651d22018-11-07 15:25:05 +0100275static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp)
276{
277 struct tlv_parsed tp;
278 int rc;
279
280 /* skip header and message type so we can parse Cause IE directly */
281 msg->l2h = msgb_data(msg) + sizeof(struct bssmap_header) + 1;
282
283 rc = osmo_bssap_tlv_parse(&tp, msg->l2h, msgb_l2len(msg));
284 if (rc < 0)
285 printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg));
286
287 rc = gsm0808_get_cipher_reject_cause(&tp);
288 if (rc < 0)
289 printf("FIXME: failed (%s) to extract Cause from created message %s\n",
290 strerror(-rc), msgb_hexdump(msg));
291
292 if (exp != (enum gsm0808_cause)rc)
293 printf("FIXME: wrong Cause %d != %u (" OSMO_BIN_SPEC ") extracted from created message %s\n",
294 rc, exp, OSMO_BIT_PRINT(exp), msgb_hexdump(msg));
295}
296
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100297static void test_create_cipher_reject()
298{
Harald Welte62e40852017-12-17 20:50:34 +0100299 static const uint8_t res[] = { 0x00, 0x04, 0x59, 0x04, 0x01, 0x23 };
Maxed651d22018-11-07 15:25:05 +0100300 enum gsm0808_cause cause = GSM0808_CAUSE_CCCH_OVERLOAD;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100301 struct msgb *msg;
302
303 printf("Testing creating Cipher Reject\n");
Maxed651d22018-11-07 15:25:05 +0100304 msg = gsm0808_create_cipher_reject(cause);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100305 VERIFY(msg, res, ARRAY_SIZE(res));
Maxed651d22018-11-07 15:25:05 +0100306
307 parse_cipher_reject(msg, cause);
308
309 msgb_free(msg);
310}
311
312static void test_create_cipher_reject_ext()
313{
314 static const uint8_t res[] = { 0x00, 0x05, 0x59, 0x04, 0x02, 0xd0, 0xFA };
315 uint8_t cause = 0xFA;
316 struct msgb *msg;
317
318 printf("Testing creating Cipher Reject (extended)\n");
319 msg = gsm0808_create_cipher_reject_ext(GSM0808_CAUSE_CLASS_INVAL, cause);
320 VERIFY(msg, res, ARRAY_SIZE(res));
321
322 parse_cipher_reject(msg, cause);
323
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100324 msgb_free(msg);
325}
326
327static void test_create_cm_u()
328{
Harald Welte07b625d2012-01-23 10:02:58 +0100329 static const uint8_t res[] = {
330 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
331 static const uint8_t res2o[] = {
332 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100333 struct msgb *msg;
Harald Welte07b625d2012-01-23 10:02:58 +0100334 const uint8_t cm2 = 0x23;
335 const uint8_t cm3 = 0x42;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100336
337 printf("Testing creating CM U\n");
Harald Welte07b625d2012-01-23 10:02:58 +0100338 msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100339 VERIFY(msg, res, ARRAY_SIZE(res));
Harald Welte07b625d2012-01-23 10:02:58 +0100340
Neels Hofmeyr9a938ae2017-11-16 17:34:07 +0100341 msgb_free(msg);
342
Harald Welte07b625d2012-01-23 10:02:58 +0100343 msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
344 VERIFY(msg, res2o, ARRAY_SIZE(res2o));
345
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100346 msgb_free(msg);
347}
348
349static void test_create_sapi_reject()
350{
351 static const uint8_t res[] = { 0x00, 0x03, 0x25, 0x03, 0x25 };
352 struct msgb *msg;
353
354 printf("Testing creating SAPI Reject\n");
355 msg = gsm0808_create_sapi_reject(3);
356 VERIFY(msg, res, ARRAY_SIZE(res));
357 msgb_free(msg);
358}
359
Philipp Maierc6144a22017-03-29 17:53:43 +0200360static void test_create_ass()
361{
362 static const uint8_t res1[] =
363 { 0x00, 0x0a, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
364 0x04 };
365 static const uint8_t res2[] =
366 { 0x00, 0x20, 0x01, 0x0b, 0x04, 0x01, 0x0b, 0xa1, 0x25, 0x01, 0x00,
367 0x04, GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17,
Philipp Maierbb839662017-06-01 17:11:19 +0200368 0x04, 0xd2, GSM0808_IE_SPEECH_CODEC_LIST, 0x07,
Philipp Maier7e27b142018-03-22 17:26:46 +0100369 GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f,
Philipp Maierbb839662017-06-01 17:11:19 +0200370 GSM0808_SCT_CSD | 0x90, 0xc0, GSM0808_IE_CALL_ID, 0xaa, 0xbb,
371 0xcc, 0xdd };
Philipp Maierc6144a22017-03-29 17:53:43 +0200372
373 struct msgb *msg;
374 struct gsm0808_channel_type ct;
375 uint16_t cic = 0004;
376 struct sockaddr_storage ss;
377 struct sockaddr_in sin;
378 struct gsm0808_speech_codec_list sc_list;
379 uint32_t call_id = 0xAABBCCDD;
380
381 memset(&ct, 0, sizeof(ct));
382 ct.ch_indctr = GSM0808_CHAN_SPEECH;
383 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
384 ct.perm_spch[0] = GSM0808_PERM_FR3;
385 ct.perm_spch[1] = GSM0808_PERM_HR3;
386 ct.perm_spch_len = 2;
387
388 memset(&sin, 0, sizeof(sin));
389 sin.sin_family = AF_INET;
390 sin.sin_port = htons(1234);
391 inet_aton("192.168.100.23", &sin.sin_addr);
392
393 memset(&ss, 0, sizeof(ss));
394 memcpy(&ss, &sin, sizeof(sin));
395
396 setup_codec_list(&sc_list);
397
398 printf("Testing creating Assignment Request\n");
399 msg = gsm0808_create_ass(&ct, &cic, NULL, NULL, NULL);
400 OSMO_ASSERT(msg);
401 VERIFY(msg, res1, ARRAY_SIZE(res1));
402 msgb_free(msg);
403
404 msg = gsm0808_create_ass(&ct, &cic, &ss, &sc_list, &call_id);
405 OSMO_ASSERT(msg);
406 VERIFY(msg, res2, ARRAY_SIZE(res2));
407 msgb_free(msg);
408}
409
Max52074322018-11-30 10:44:07 +0100410static void test_create_ass2()
411{
412 static const uint8_t res[] = {
413 BSSAP_MSG_BSS_MANAGEMENT,
414 0x45,
415 BSS_MAP_MSG_ASSIGMENT_RQST,
416 GSM0808_IE_CHANNEL_TYPE,
417 0x04, 0x01, 0x0b, 0x91, 0x15, 0x01, 0x00, 0x04,
418 GSM0808_IE_AOIP_TRASP_ADDR,
419 0x06,
420 0xac, 0x0c, 0x65, 0x0d, /* IPv4 */
421 0x02, 0x9a,
422 GSM0808_IE_SPEECH_CODEC_LIST,
423 0x07,
424 GSM0808_SCT_FR3 | 0x50,
425 0xef, 0xcd,
426 GSM0808_SCT_FR2 | 0xa0,
427 0x9f,
428 GSM0808_SCT_CSD | 0x90,
429 0xc0,
430 GSM0808_IE_CALL_ID,
431 0xde, 0xad, 0xfa, 0xce, /* CallID */
432 0x83, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, /* Kc */
433 GSM0808_IE_GLOBAL_CALL_REF, 0x0d, /* GCR, length */
434 0x03, 0x44, 0x44, 0x44, /* GCR, Net ID */
435 0x02, 0xfe, 0xed, /* GCR, Node ID */
436 0x05, 0x41, 0x41, 0x41, 0x41, 0x41, /* GCR, Call ref. ID */
437 GSM0808_IE_LCLS_CONFIG, GSM0808_LCLS_CFG_BOTH_WAY,
438 GSM0808_IE_LCLS_CONN_STATUS_CTRL, GSM0808_LCLS_CSC_CONNECT,
439 GSM0808_IE_LCLS_CORR_NOT_NEEDED,
440 };
441 struct msgb *msg;
442 struct gsm0808_channel_type ct;
443 uint16_t cic = 4;
444 struct sockaddr_storage ss;
445 struct sockaddr_in sin;
446 struct gsm0808_speech_codec_list sc_list;
447 uint32_t call_id = 0xDEADFACE;
Max52074322018-11-30 10:44:07 +0100448 uint8_t Kc[16];
449 struct osmo_lcls lcls = {
450 .config = GSM0808_LCLS_CFG_BOTH_WAY,
451 .control = GSM0808_LCLS_CSC_CONNECT,
Max3b901252019-01-15 14:15:11 +0100452 .gcr = { .net_len = 3, .node = 0xFEED },
453 .gcr_available = true,
Max52074322018-11-30 10:44:07 +0100454 .corr_needed = false
455 };
456
Max3b901252019-01-15 14:15:11 +0100457 memset(lcls.gcr.cr, 'A', 5);
458 memset(lcls.gcr.net, 'D', lcls.gcr.net_len);
Max52074322018-11-30 10:44:07 +0100459 memset(Kc, 'E', 16);
460
461 memset(&ct, 0, sizeof(ct));
462 ct.ch_indctr = GSM0808_CHAN_SPEECH;
463 ct.ch_rate_type = GSM0808_SPEECH_HALF_PREF;
464 ct.perm_spch[0] = GSM0808_PERM_FR2;
465 ct.perm_spch[1] = GSM0808_PERM_HR2;
466 ct.perm_spch_len = 2;
467
468 memset(&sin, 0, sizeof(sin));
469 sin.sin_family = AF_INET;
470 sin.sin_port = htons(666);
471 inet_aton("172.12.101.13", &sin.sin_addr); /* IPv4 */
472
473 memset(&ss, 0, sizeof(ss));
474 memcpy(&ss, &sin, sizeof(sin));
475
476 setup_codec_list(&sc_list);
477
478 printf("Testing creating Assignment Request with Kc and LCLS\n");
479
480 msg = gsm0808_create_ass2(&ct, &cic, &ss, &sc_list, &call_id, Kc, &lcls);
481 if (!msgb_eq_l3_data_print(msg, res, ARRAY_SIZE(res)))
482 abort();
483
484 msgb_free(msg);
485}
486
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100487static void test_create_ass_compl()
488{
489 static const uint8_t res1[] = {
490 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
491 0x11, 0x40, 0x22 };
492 static const uint8_t res2[] = {
493 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
494 struct msgb *msg;
495
496 printf("Testing creating Assignment Complete\n");
497 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
498 VERIFY(msg, res1, ARRAY_SIZE(res1));
499 msgb_free(msg);
500
501 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
502 VERIFY(msg, res2, ARRAY_SIZE(res2));
503 msgb_free(msg);
504}
505
Philipp Maierfa896ab2017-03-27 16:55:32 +0200506static void test_create_ass_compl_aoip()
507{
508 struct sockaddr_storage ss;
509 struct sockaddr_in sin;
510 struct gsm0808_speech_codec sc;
511 struct gsm0808_speech_codec_list sc_list;
512 static const uint8_t res[] =
Max414c8f52019-01-08 14:44:24 +0100513 { 0x00, 0x1f, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11, 0x40, 0x22,
Philipp Maierfa896ab2017-03-27 16:55:32 +0200514 GSM0808_IE_AOIP_TRASP_ADDR, 0x06, 0xc0, 0xa8, 0x64, 0x17, 0x04,
Philipp Maierbb839662017-06-01 17:11:19 +0200515 0xd2, GSM0808_IE_SPEECH_CODEC, 0x01, GSM0808_SCT_HR1 | 0x90,
Philipp Maier7e27b142018-03-22 17:26:46 +0100516 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
Max414c8f52019-01-08 14:44:24 +0100517 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0,
518 GSM0808_IE_LCLS_BSS_STATUS, GSM0808_LCLS_STS_LOCALLY_SWITCHED };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200519 struct msgb *msg;
520
521 memset(&sin, 0, sizeof(sin));
522 sin.sin_family = AF_INET;
523 sin.sin_port = htons(1234);
524 inet_aton("192.168.100.23", &sin.sin_addr);
525
526 memset(&ss, 0, sizeof(ss));
527 memcpy(&ss, &sin, sizeof(sin));
528
529 memset(&sc, 0, sizeof(sc));
530 sc.fi = true;
531 sc.tf = true;
Philipp Maierbb839662017-06-01 17:11:19 +0200532 sc.type = GSM0808_SCT_HR1;
Philipp Maierfa896ab2017-03-27 16:55:32 +0200533
534 setup_codec_list(&sc_list);
535
536 printf("Testing creating Assignment Complete (AoIP)\n");
Max414c8f52019-01-08 14:44:24 +0100537 msg = gsm0808_create_ass_compl2(0x23, 0x42, 0x11, 0x22,
538 &ss, &sc, &sc_list, GSM0808_LCLS_STS_LOCALLY_SWITCHED);
Philipp Maierfa896ab2017-03-27 16:55:32 +0200539 VERIFY(msg, res, ARRAY_SIZE(res));
540 msgb_free(msg);
541}
542
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100543static void test_create_ass_fail()
544{
545 static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
546 static const uint8_t res2[] = {
547 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
548 uint8_t rr_res = 2;
549 struct msgb *msg;
550
551 printf("Testing creating Assignment Failure\n");
552 msg = gsm0808_create_assignment_failure(0x23, NULL);
553 VERIFY(msg, res1, ARRAY_SIZE(res1));
554 msgb_free(msg);
555
556 msg = gsm0808_create_assignment_failure(0x23, &rr_res);
557 VERIFY(msg, res2, ARRAY_SIZE(res2));
558 msgb_free(msg);
559}
560
Philipp Maierfa896ab2017-03-27 16:55:32 +0200561static void test_create_ass_fail_aoip()
562{
563 static const uint8_t res1[] =
564 { 0x00, 0x0d, 0x03, 0x04, 0x01, 0x23, GSM0808_IE_SPEECH_CODEC_LIST,
Philipp Maier7e27b142018-03-22 17:26:46 +0100565 0x07, GSM0808_SCT_FR3 | 0x50, 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0,
Philipp Maierbb839662017-06-01 17:11:19 +0200566 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200567 static const uint8_t res2[] =
568 { 0x00, 0x0f, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02,
Philipp Maier7e27b142018-03-22 17:26:46 +0100569 GSM0808_IE_SPEECH_CODEC_LIST, 0x07, GSM0808_SCT_FR3 | 0x50, 0xef,
570 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 };
Philipp Maierfa896ab2017-03-27 16:55:32 +0200571 uint8_t rr_res = 2;
572 struct msgb *msg;
573 struct gsm0808_speech_codec_list sc_list;
574
575 setup_codec_list(&sc_list);
576
577 printf("Testing creating Assignment Failure (AoIP)\n");
578 msg = gsm0808_create_ass_fail(0x23, NULL, &sc_list);
579 VERIFY(msg, res1, ARRAY_SIZE(res1));
580 msgb_free(msg);
581
582 msg = gsm0808_create_ass_fail(0x23, &rr_res, &sc_list);
583 VERIFY(msg, res2, ARRAY_SIZE(res2));
584 msgb_free(msg);
585}
586
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100587static void test_create_clear_rqst()
588{
589 static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
590 struct msgb *msg;
591
592 printf("Testing creating Clear Request\n");
593 msg = gsm0808_create_clear_rqst(0x23);
594 VERIFY(msg, res, ARRAY_SIZE(res));
595 msgb_free(msg);
596}
597
Philipp Maier3d48ec02017-03-29 17:37:55 +0200598static void test_create_paging()
599{
600 static const uint8_t res[] =
601 { 0x00, 0x10, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
602 0x21, 0x43, 0x1a, 0x03, 0x05, 0x23, 0x42 };
603 static const uint8_t res2[] =
604 { 0x00, 0x16, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
605 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
606 0x03, 0x05, 0x23, 0x42 };
607 static const uint8_t res3[] =
608 { 0x00, 0x18, 0x52, 0x08, 0x08, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00,
609 0x21, 0x43, GSM0808_IE_TMSI, 0x04, 0x12, 0x34, 0x56, 0x78, 0x1a,
610 0x03, 0x05, 0x23, 0x42, GSM0808_IE_CHANNEL_NEEDED,
611 RSL_CHANNEED_TCH_ForH };
612
613 struct msgb *msg;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100614 struct gsm0808_cell_id_list2 cil;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200615 uint32_t tmsi = 0x12345678;
616 uint8_t chan_needed = RSL_CHANNEED_TCH_ForH;
617
618 char imsi[] = "001010000001234";
619
620 cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100621 cil.id_list[0].lac = 0x2342;
Philipp Maier3d48ec02017-03-29 17:37:55 +0200622 cil.id_list_len = 1;
623
624 printf("Testing creating Paging Request\n");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100625 msg = gsm0808_create_paging2(imsi, NULL, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200626 VERIFY(msg, res, ARRAY_SIZE(res));
627 msgb_free(msg);
628
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100629 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, NULL);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200630 VERIFY(msg, res2, ARRAY_SIZE(res2));
631 msgb_free(msg);
632
Stefan Sperling11a4d9d2018-02-15 18:28:04 +0100633 msg = gsm0808_create_paging2(imsi, &tmsi, &cil, &chan_needed);
Philipp Maier3d48ec02017-03-29 17:37:55 +0200634 VERIFY(msg, res3, ARRAY_SIZE(res3));
635 msgb_free(msg);
636}
637
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100638static void test_create_dtap()
639{
640 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
641 struct msgb *msg, *l3;
642
643 printf("Testing creating DTAP\n");
644 l3 = msgb_alloc_headroom(512, 128, "test");
645 l3->l3h = l3->data;
646 msgb_v_put(l3, 0x23);
647 msgb_v_put(l3, 0x42);
648
649 msg = gsm0808_create_dtap(l3, 0x3);
650 VERIFY(msg, res, ARRAY_SIZE(res));
651 msgb_free(msg);
652 msgb_free(l3);
653}
654
655static void test_prepend_dtap()
656{
657 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
658 struct msgb *in_msg;
659
660 printf("Testing prepend DTAP\n");
661
662 in_msg = msgb_alloc_headroom(512, 128, "test");
663 msgb_v_put(in_msg, 0x23);
664 msgb_v_put(in_msg, 0x42);
665
666 gsm0808_prepend_dtap_header(in_msg, 0x3);
667 in_msg->l3h = in_msg->data;
668 VERIFY(in_msg, res, ARRAY_SIZE(res));
669 msgb_free(in_msg);
670}
671
Max47022152018-12-19 18:51:00 +0100672static void test_enc_dec_lcls()
Max969fb2e2018-12-10 11:01:10 +0100673{
674 static const uint8_t res[] = {
675 GSM0808_IE_GLOBAL_CALL_REF,
676 0x0d, /* GCR length */
677 0x03, /* .net_len */
678 0xf1, 0xf2, 0xf3, /* .net */
679 0x02, /* .node length */
680 0xde, 0xad, /* .node */
681 0x05, /* length of Call. Ref. */
682 0x41, 0x42, 0x43, 0x44, 0x45 /* .cr - Call. Ref. */
683 };
684 uint8_t len;
685 struct msgb *msg;
Max969fb2e2018-12-10 11:01:10 +0100686 int rc;
687 struct tlv_parsed tp;
Max3b901252019-01-15 14:15:11 +0100688 struct osmo_lcls *lcls_out, lcls_in = {
689 .gcr = {
690 .net_len = 3,
691 .net = { 0xf1, 0xf2, 0xf3 },
692 .node = 0xDEAD,
693 .cr = { 0x41, 0x42, 0x43, 0x44, 0x45 },
694 },
695 .gcr_available = true,
Max47022152018-12-19 18:51:00 +0100696 .config = GSM0808_LCLS_CFG_NA,
697 .control = GSM0808_LCLS_CSC_NA,
698 .corr_needed = true,
699 };
700
701 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "LCLS IE");
Max969fb2e2018-12-10 11:01:10 +0100702 if (!msg)
703 return;
704
Max3b901252019-01-15 14:15:11 +0100705 lcls_out = talloc_zero(msg, struct osmo_lcls);
706 if (!lcls_out)
707 return;
708
Max47022152018-12-19 18:51:00 +0100709 len = gsm0808_enc_lcls(msg, &lcls_in);
Max969fb2e2018-12-10 11:01:10 +0100710 printf("Testing Global Call Reference IE encoder...\n\t%d bytes added: %s\n",
711 len, len == ARRAY_SIZE(res) ? "OK" : "FAIL");
712
713 if (!msgb_eq_data_print(msg, res, ARRAY_SIZE(res)))
714 abort();
715
716 rc = osmo_bssap_tlv_parse(&tp, msgb_data(msg), msgb_length(msg));
717 if (rc < 0) {
718 printf("parsing failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
719 abort();
720 }
721
Max3b901252019-01-15 14:15:11 +0100722 rc = gsm0808_dec_lcls(lcls_out, &tp);
Max969fb2e2018-12-10 11:01:10 +0100723 if (rc < 0) {
724 printf("decoding failed: %s [%s]\n", strerror(-rc), msgb_hexdump(msg));
725 abort();
726 }
727
Max3b901252019-01-15 14:15:11 +0100728 if (lcls_out->config != lcls_in.config) {
Max4fd64e52019-01-14 19:27:44 +0100729 printf("LCLS Config parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100730 gsm0808_lcls_config_name(lcls_out->config), gsm0808_lcls_config_name(lcls_in.config));
Max4fd64e52019-01-14 19:27:44 +0100731 abort();
732 }
733
Max3b901252019-01-15 14:15:11 +0100734 if (lcls_out->control != lcls_in.control) {
Max4fd64e52019-01-14 19:27:44 +0100735 printf("LCLS Control parsed wrong: %s != %s\n",
Max3b901252019-01-15 14:15:11 +0100736 gsm0808_lcls_control_name(lcls_out->control), gsm0808_lcls_control_name(lcls_in.control));
Max4fd64e52019-01-14 19:27:44 +0100737 abort();
738 }
739
Max3b901252019-01-15 14:15:11 +0100740 if (!osmo_gcr_eq(&lcls_out->gcr, &lcls_in.gcr)) {
Max1bec3902019-01-14 19:31:42 +0100741 printf("GCR parsed wrong.\n");
742 abort();
743 }
Max969fb2e2018-12-10 11:01:10 +0100744
745 printf("\tdecoded %d bytes: %s\n", rc, rc == len ? "OK" : "FAIL");
746 msgb_free(msg);
747}
748
Philipp Maier22401432017-03-24 17:59:26 +0100749static void test_enc_dec_aoip_trasp_addr_v4()
750{
751 struct sockaddr_storage enc_addr;
752 struct sockaddr_storage dec_addr;
753 struct sockaddr_in enc_addr_in;
754 struct msgb *msg;
755 uint8_t rc_enc;
756 int rc_dec;
757
758 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
759 enc_addr_in.sin_family = AF_INET;
760 enc_addr_in.sin_port = htons(1234);
761 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
762
763 memset(&enc_addr, 0, sizeof(enc_addr));
764 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
765
766 msg = msgb_alloc(1024, "output buffer");
767 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
768 OSMO_ASSERT(rc_enc == 8);
769 rc_dec =
770 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
771 OSMO_ASSERT(rc_dec == 6);
772 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
773
774 msgb_free(msg);
775}
776
777static void test_enc_dec_aoip_trasp_addr_v6()
778{
779 struct sockaddr_storage enc_addr;
780 struct sockaddr_storage dec_addr;
781 struct sockaddr_in6 enc_addr_in;
782 struct msgb *msg;
783 uint8_t rc_enc;
784 int rc_dec;
785
786 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
787 enc_addr_in.sin6_family = AF_INET6;
788 enc_addr_in.sin6_port = htons(4567);
789 inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
790 &enc_addr_in.sin6_addr);
791
792 memset(&enc_addr, 0, sizeof(enc_addr));
793 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
794
795 msg = msgb_alloc(1024, "output buffer");
796 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
797 OSMO_ASSERT(rc_enc == 20);
798 rc_dec =
799 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
800 OSMO_ASSERT(rc_dec == 18);
801 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
802
803 msgb_free(msg);
804}
805
Philipp Maier6f725d62017-03-24 18:03:17 +0100806static void test_gsm0808_enc_dec_speech_codec()
807{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200808 struct gsm0808_speech_codec enc_sc = {
809 .pi = true,
810 .tf = true,
811 .type = GSM0808_SCT_FR2,
812 };
813 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100814 struct msgb *msg;
815 uint8_t rc_enc;
816 int rc_dec;
817
Philipp Maier6f725d62017-03-24 18:03:17 +0100818 msg = msgb_alloc(1024, "output buffer");
819 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
820 OSMO_ASSERT(rc_enc == 3);
821
822 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
823 OSMO_ASSERT(rc_dec == 1);
824
825 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
826
827 msgb_free(msg);
828}
829
830
Philipp Maierbb839662017-06-01 17:11:19 +0200831static void test_gsm0808_enc_dec_speech_codec_with_cfg()
832{
Neels Hofmeyrc62c9342018-04-15 23:31:47 +0200833 struct gsm0808_speech_codec enc_sc = {
834 .pi = true,
835 .tf = true,
836 .type = GSM0808_SCT_FR3,
837 .cfg = 0xabcd,
838 };
839 struct gsm0808_speech_codec dec_sc = {};
Philipp Maierbb839662017-06-01 17:11:19 +0200840 struct msgb *msg;
841 uint8_t rc_enc;
842 int rc_dec;
843
Philipp Maierbb839662017-06-01 17:11:19 +0200844 msg = msgb_alloc(1024, "output buffer");
845 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
846 OSMO_ASSERT(rc_enc == 5);
847
848 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
849 OSMO_ASSERT(rc_dec == 3);
850
851 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
852
853 msgb_free(msg);
854}
855
Philipp Maier6f725d62017-03-24 18:03:17 +0100856static void test_gsm0808_enc_dec_speech_codec_ext_with_cfg()
857{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200858 struct gsm0808_speech_codec enc_sc = {
859 .pi = true,
860 .tf = true,
861 .type = GSM0808_SCT_CSD,
862 .cfg = 0xc0,
863 };
864 struct gsm0808_speech_codec dec_sc = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100865 struct msgb *msg;
866 uint8_t rc_enc;
867 int rc_dec;
868
Philipp Maier6f725d62017-03-24 18:03:17 +0100869 msg = msgb_alloc(1024, "output buffer");
870 rc_enc = gsm0808_enc_speech_codec(msg, &enc_sc);
Philipp Maierbb839662017-06-01 17:11:19 +0200871 OSMO_ASSERT(rc_enc == 5);
Philipp Maier6f725d62017-03-24 18:03:17 +0100872
873 rc_dec = gsm0808_dec_speech_codec(&dec_sc, msg->data + 2, msg->len - 2);
Philipp Maierbb839662017-06-01 17:11:19 +0200874 OSMO_ASSERT(rc_dec == 3);
Philipp Maier6f725d62017-03-24 18:03:17 +0100875
876 OSMO_ASSERT(memcmp(&enc_sc, &dec_sc, sizeof(enc_sc)) == 0);
877
878 msgb_free(msg);
879}
880
881static void test_gsm0808_enc_dec_speech_codec_list()
882{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200883 struct gsm0808_speech_codec_list enc_scl = {
884 .codec = {
885 {
886 .pi = true,
887 .tf = true,
888 .type = GSM0808_SCT_FR3,
889 .cfg = 0xcdef,
890 },
891
892 {
893 .fi = true,
894 .pt = true,
895 .type = GSM0808_SCT_FR2,
896 },
897
898 {
899 .fi = true,
900 .tf = true,
901 .type = GSM0808_SCT_CSD,
902 .cfg = 0xc0,
903 },
904 },
905 .len = 3,
906 };
907 struct gsm0808_speech_codec_list dec_scl = {};
Philipp Maier6f725d62017-03-24 18:03:17 +0100908 struct msgb *msg;
909 uint8_t rc_enc;
910 int rc_dec;
911
Philipp Maier6f725d62017-03-24 18:03:17 +0100912 msg = msgb_alloc(1024, "output buffer");
913 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
914 OSMO_ASSERT(rc_enc == 9);
915
916 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
917 OSMO_ASSERT(rc_dec == 7);
918
919 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
920
921 msgb_free(msg);
922}
923
Philipp Maierf6c369f2018-10-16 15:24:47 +0200924static void test_gsm0808_enc_dec_empty_speech_codec_list()
925{
926 struct gsm0808_speech_codec_list enc_scl = {
927 .len = 0,
928 };
929 struct gsm0808_speech_codec_list dec_scl = {};
930 struct msgb *msg;
931 uint8_t rc_enc;
932 int rc_dec;
933
934 msg = msgb_alloc(1024, "output buffer");
935 rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl);
936 OSMO_ASSERT(rc_enc == 2);
937
938 rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2);
939 OSMO_ASSERT(rc_dec == 0);
940
941 OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0);
942
943 msgb_free(msg);
944}
945
Philipp Maiere0c65302017-03-28 17:05:40 +0200946static void test_gsm0808_enc_dec_channel_type()
947{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200948 struct gsm0808_channel_type enc_ct = {
949 .ch_indctr = GSM0808_CHAN_SPEECH,
950 .ch_rate_type = GSM0808_SPEECH_HALF_PREF,
951 .perm_spch = { GSM0808_PERM_FR3, GSM0808_PERM_HR3 },
952 .perm_spch_len = 2,
953 };
954 struct gsm0808_channel_type dec_ct = {};
Philipp Maiere0c65302017-03-28 17:05:40 +0200955 struct msgb *msg;
956 uint8_t ct_enc_expected[] = { GSM0808_IE_CHANNEL_TYPE,
957 0x04, 0x01, 0x0b, 0xa1, 0x25
958 };
959 uint8_t rc_enc;
960 int rc_dec;
961
Philipp Maiere0c65302017-03-28 17:05:40 +0200962 msg = msgb_alloc(1024, "output buffer");
963 rc_enc = gsm0808_enc_channel_type(msg, &enc_ct);
964 OSMO_ASSERT(rc_enc == 6);
965 OSMO_ASSERT(memcmp(ct_enc_expected, msg->data, msg->len) == 0);
966
967 rc_dec = gsm0808_dec_channel_type(&dec_ct, msg->data + 2, msg->len - 2);
968 OSMO_ASSERT(rc_dec == 4);
969 OSMO_ASSERT(memcmp(&enc_ct, &dec_ct, sizeof(enc_ct)) == 0);
970
971 msgb_free(msg);
972}
973
Philipp Maier14e76b92017-03-28 18:36:52 +0200974static void test_gsm0808_enc_dec_encrypt_info()
975{
Neels Hofmeyr9a4286b2018-04-20 12:27:52 +0200976 struct gsm0808_encrypt_info enc_ei = {
977 .perm_algo = { GSM0808_ALG_ID_A5_0, GSM0808_ALG_ID_A5_1 },
978 .perm_algo_len = 2,
979 .key = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42, },
980 .key_len = 8,
981 };
982 struct gsm0808_encrypt_info dec_ei = {};
Philipp Maier14e76b92017-03-28 18:36:52 +0200983 struct msgb *msg;
984 uint8_t ei_enc_expected[] =
985 { GSM0808_IE_ENCRYPTION_INFORMATION, 0x09, 0x03, 0xaa, 0xbb,
986 0xcc, 0xdd, 0xee, 0xff, 0x23, 0x42
987 };
988 uint8_t rc_enc;
989 int rc_dec;
990
Philipp Maier14e76b92017-03-28 18:36:52 +0200991 msg = msgb_alloc(1024, "output buffer");
992 rc_enc = gsm0808_enc_encrypt_info(msg, &enc_ei);
993 OSMO_ASSERT(rc_enc == 11);
994 OSMO_ASSERT(memcmp(ei_enc_expected, msg->data, msg->len) == 0);
995
996 rc_dec = gsm0808_dec_encrypt_info(&dec_ei, msg->data + 2, msg->len - 2);
997 OSMO_ASSERT(rc_dec == 9);
998
999 OSMO_ASSERT(memcmp(&enc_ei, &dec_ei, sizeof(enc_ei)) == 0);
1000
1001 msgb_free(msg);
1002}
1003
Philipp Maier783047e2017-03-29 11:35:50 +02001004static void test_gsm0808_enc_dec_cell_id_list_lac()
1005{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001006 struct gsm0808_cell_id_list2 enc_cil;
1007 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001008 struct msgb *msg;
1009 uint8_t rc_enc;
1010 int rc_dec;
1011
1012 memset(&enc_cil, 0, sizeof(enc_cil));
1013 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001014 enc_cil.id_list[0].lac = 0x0124;
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001015 enc_cil.id_list[1].lac = 0xABCD;
1016 enc_cil.id_list[2].lac = 0x5678;
Philipp Maier783047e2017-03-29 11:35:50 +02001017 enc_cil.id_list_len = 3;
1018
1019 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001020 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Neels Hofmeyrdb2fa4e2018-04-13 04:11:20 +02001021 EXPECT_ENCODED("1a 07 05 01 24 ab cd 56 78");
Philipp Maier783047e2017-03-29 11:35:50 +02001022
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001023 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001024 OSMO_ASSERT(rc_dec == 7);
1025
1026 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1027
1028 msgb_free(msg);
1029}
1030
1031static void test_gsm0808_enc_dec_cell_id_list_single_lac()
1032{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001033 struct gsm0808_cell_id_list2 enc_cil;
1034 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001035 struct msgb *msg;
1036 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x03,
1037 0x05, 0x23, 0x42
1038 };
1039 uint8_t rc_enc;
1040 int rc_dec;
1041
1042 memset(&enc_cil, 0, sizeof(enc_cil));
1043 enc_cil.id_discr = CELL_IDENT_LAC;
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001044 enc_cil.id_list[0].lac = 0x2342;
Philipp Maier783047e2017-03-29 11:35:50 +02001045 enc_cil.id_list_len = 1;
1046
1047 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001048 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001049 OSMO_ASSERT(rc_enc == 5);
1050 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1051
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001052 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001053 OSMO_ASSERT(rc_dec == 3);
1054
1055 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1056
1057 msgb_free(msg);
1058}
1059
Stefan Sperlinge1a86742018-03-15 18:05:02 +01001060static void test_gsm0808_enc_dec_cell_id_list_multi_lac()
1061{
1062 struct gsm0808_cell_id_list2 enc_cil;
1063 struct gsm0808_cell_id_list2 dec_cil;
1064 struct msgb *msg;
1065 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x0b, 0x05,
1066 0x23, 0x42,
1067 0x24, 0x43,
1068 0x25, 0x44,
1069 0x26, 0x45,
1070 0x27, 0x46
1071 };
1072 uint8_t rc_enc;
1073 int rc_dec;
1074
1075 memset(&enc_cil, 0, sizeof(enc_cil));
1076 enc_cil.id_discr = CELL_IDENT_LAC;
1077 enc_cil.id_list[0].lac = 0x2342;
1078 enc_cil.id_list[1].lac = 0x2443;
1079 enc_cil.id_list[2].lac = 0x2544;
1080 enc_cil.id_list[3].lac = 0x2645;
1081 enc_cil.id_list[4].lac = 0x2746;
1082 enc_cil.id_list_len = 5;
1083
1084 msg = msgb_alloc(1024, "output buffer");
1085 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1086 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1087 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1088
1089 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1090 OSMO_ASSERT(rc_dec == msg->len - 2);
1091 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1092
1093 msgb_free(msg);
1094}
1095
Philipp Maier783047e2017-03-29 11:35:50 +02001096static void test_gsm0808_enc_dec_cell_id_list_bss()
1097{
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001098 struct gsm0808_cell_id_list2 enc_cil;
1099 struct gsm0808_cell_id_list2 dec_cil;
Philipp Maier783047e2017-03-29 11:35:50 +02001100 struct msgb *msg;
1101 uint8_t rc_enc;
1102 int rc_dec;
1103
1104 memset(&enc_cil, 0, sizeof(enc_cil));
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001105 enc_cil.id_discr = CELL_IDENT_BSS;
Philipp Maier783047e2017-03-29 11:35:50 +02001106
1107 msg = msgb_alloc(1024, "output buffer");
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001108 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
Philipp Maier783047e2017-03-29 11:35:50 +02001109 OSMO_ASSERT(rc_enc == 3);
1110
Stefan Sperling11a4d9d2018-02-15 18:28:04 +01001111 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
Philipp Maier783047e2017-03-29 11:35:50 +02001112 OSMO_ASSERT(rc_dec == 1);
1113
1114 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1115
1116 msgb_free(msg);
1117}
1118
Stefan Sperling23381452018-03-15 19:38:15 +01001119static void test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac()
1120{
1121 struct gsm0808_cell_id_list2 enc_cil;
1122 struct gsm0808_cell_id_list2 dec_cil;
1123 struct osmo_location_area_id id;
1124 struct msgb *msg;
1125 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x10, 0x04,
1126 0x92, 0x61, 0x54, 0x23, 0x42,
1127 0x92, 0x72, 0x54, 0x24, 0x43,
1128 0x92, 0x83, 0x54, 0x25, 0x44
1129 };
1130 uint8_t rc_enc;
1131 int rc_dec, i;
1132
1133 memset(&enc_cil, 0, sizeof(enc_cil));
1134 enc_cil.id_discr = CELL_IDENT_LAI_AND_LAC;
1135
1136 id.plmn.mcc = 0x123;
1137 osmo_mnc_from_str("456", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1138 id.lac = 0x2342;
1139 memcpy(&enc_cil.id_list[0].lai_and_lac, &id, sizeof(id));
1140
1141 id.plmn.mcc = 0x124;
1142 osmo_mnc_from_str("457", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1143 id.lac = 0x2443;
1144 memcpy(&enc_cil.id_list[1].lai_and_lac, &id, sizeof(id));
1145
1146 id.plmn.mcc = 0x125;
1147 osmo_mnc_from_str("458", &id.plmn.mnc, &id.plmn.mnc_3_digits);
1148 id.lac = 0x2544;
1149 memcpy(&enc_cil.id_list[2].lai_and_lac, &id, sizeof(id));
1150
1151 enc_cil.id_list_len = 3;
1152
1153 msg = msgb_alloc(1024, "output buffer");
1154 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1155 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1156 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1157
1158 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1159 OSMO_ASSERT(rc_dec == msg->len - 2);
1160
1161 OSMO_ASSERT(dec_cil.id_list_len == 3);
1162 /* Check MAXLEN elements to ensure everything has been initialized. */
1163 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1164 struct osmo_location_area_id *enc_id;
1165 struct osmo_location_area_id *dec_id;
1166 enc_id = &enc_cil.id_list[i].lai_and_lac;
1167 dec_id = &dec_cil.id_list[i].lai_and_lac;
1168 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->plmn, &dec_id->plmn) == 0);
1169 OSMO_ASSERT(enc_id->lac == dec_id->lac);
1170 }
1171
1172 msgb_free(msg);
1173}
1174
Stefan Sperling9c62fc62018-03-16 10:23:34 +01001175static void test_gsm0808_enc_dec_cell_id_list_multi_ci()
1176{
1177 struct gsm0808_cell_id_list2 enc_cil;
1178 struct gsm0808_cell_id_list2 dec_cil;
1179 struct msgb *msg;
1180 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x09, 0x02,
1181 0x00, 0x01,
1182 0x00, 0x02,
1183 0x00, 0x77,
1184 0x01, 0xff,
1185 };
1186 uint8_t rc_enc;
1187 int rc_dec;
1188
1189 memset(&enc_cil, 0, sizeof(enc_cil));
1190 enc_cil.id_discr = CELL_IDENT_CI;
1191 enc_cil.id_list[0].ci = 1;
1192 enc_cil.id_list[1].ci = 2;
1193 enc_cil.id_list[2].ci = 119;
1194 enc_cil.id_list[3].ci = 511;
1195 enc_cil.id_list_len = 4;
1196
1197 msg = msgb_alloc(1024, "output buffer");
1198 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1199 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1200 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1201
1202 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1203 OSMO_ASSERT(rc_dec == msg->len - 2);
1204 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1205
1206 msgb_free(msg);
1207}
1208
Stefan Sperlinged4327c2018-03-16 11:02:59 +01001209static void test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci()
1210{
1211 struct gsm0808_cell_id_list2 enc_cil;
1212 struct gsm0808_cell_id_list2 dec_cil;
1213 struct msgb *msg;
1214 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x15, 0x01,
1215 0x23, 0x42, 0x00, 0x01,
1216 0x24, 0x43, 0x00, 0x02,
1217 0x25, 0x44, 0x00, 0x77,
1218 0x26, 0x45, 0x01, 0xff,
1219 0x27, 0x46, 0x02, 0xfe,
1220 };
1221 uint8_t rc_enc;
1222 int rc_dec;
1223
1224 memset(&enc_cil, 0, sizeof(enc_cil));
1225 enc_cil.id_discr = CELL_IDENT_LAC_AND_CI;
1226 enc_cil.id_list[0].lac_and_ci.lac = 0x2342;
1227 enc_cil.id_list[0].lac_and_ci.ci = 1;
1228 enc_cil.id_list[1].lac_and_ci.lac = 0x2443;
1229 enc_cil.id_list[1].lac_and_ci.ci = 2;
1230 enc_cil.id_list[2].lac_and_ci.lac = 0x2544;
1231 enc_cil.id_list[2].lac_and_ci.ci = 119;
1232 enc_cil.id_list[3].lac_and_ci.lac = 0x2645;
1233 enc_cil.id_list[3].lac_and_ci.ci = 511;
1234 enc_cil.id_list[4].lac_and_ci.lac = 0x2746;
1235 enc_cil.id_list[4].lac_and_ci.ci = 766;
1236 enc_cil.id_list_len = 5;
1237
1238 msg = msgb_alloc(1024, "output buffer");
1239 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1240 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
1241 OSMO_ASSERT(memcmp(cil_enc_expected, msg->data, msg->len) == 0);
1242
1243 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1244 OSMO_ASSERT(rc_dec == msg->len - 2);
1245 OSMO_ASSERT(memcmp(&enc_cil, &dec_cil, sizeof(enc_cil)) == 0);
1246
1247 msgb_free(msg);
1248}
1249
Stefan Sperling483f3862018-03-16 12:21:26 +01001250static void test_gsm0808_enc_dec_cell_id_list_multi_global()
1251{
1252 struct gsm0808_cell_id_list2 enc_cil;
1253 struct gsm0808_cell_id_list2 dec_cil;
1254 struct msgb *msg;
1255 uint8_t cil_enc_expected[] = { GSM0808_IE_CELL_IDENTIFIER_LIST, 0x16, 0x00,
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001256 0x21, 0x63, 0x54, 0x23, 0x42, 0x00, 0x1,
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001257 0x21, 0xf4, 0x75, 0x24, 0x43, 0x00, 0x2,
Neels Hofmeyr8b8cd932018-03-23 01:47:37 +01001258 0x21, 0x75, 0x00, 0x25, 0x44, 0x00, 0x77
Stefan Sperling483f3862018-03-16 12:21:26 +01001259 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001260 uint8_t rc_enc;
1261 int rc_dec, i;
1262
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001263 enc_cil = (struct gsm0808_cell_id_list2){
1264 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1265 .id_list_len = 3,
1266 .id_list = {
1267 {
1268 .global = {
Neels Hofmeyr473485c2018-03-23 02:04:18 +01001269 .lai = { .plmn = { .mcc = 123, .mnc = 456 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001270 .lac = 0x2342 },
1271 .cell_identity = 1,
1272 }
1273 },
1274 {
1275 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001276 .lai = { .plmn = { .mcc = 124, .mnc = 57 },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001277 .lac = 0x2443 },
1278 .cell_identity = 2,
1279 }
1280 },
1281 {
1282 .global = {
Neels Hofmeyrc44fc232018-03-23 02:15:12 +01001283 .lai = { .plmn = { .mcc = 125, .mnc = 7,
1284 .mnc_3_digits = true },
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001285 .lac = 0x2544 },
1286 .cell_identity = 119,
1287 }
1288 },
1289 }
1290 };
Stefan Sperling483f3862018-03-16 12:21:26 +01001291
1292 msg = msgb_alloc(1024, "output buffer");
1293 rc_enc = gsm0808_enc_cell_id_list2(msg, &enc_cil);
1294 OSMO_ASSERT(rc_enc == sizeof(cil_enc_expected));
Neels Hofmeyrc1991df2018-03-23 02:00:00 +01001295 if (memcmp(cil_enc_expected, msg->data, msg->len)) {
1296 printf(" got: %s\n", osmo_hexdump(msg->data, msg->len));
1297 printf("expect: %s\n", osmo_hexdump(cil_enc_expected, sizeof(cil_enc_expected)));
1298 OSMO_ASSERT(false);
1299 }
Stefan Sperling483f3862018-03-16 12:21:26 +01001300
1301 rc_dec = gsm0808_dec_cell_id_list2(&dec_cil, msg->data + 2, msg->len - 2);
1302 OSMO_ASSERT(rc_dec == msg->len - 2);
1303
1304 /* Check MAXLEN elements to ensure everything has been initialized. */
1305 for (i = 0; i < GSM0808_CELL_ID_LIST2_MAXLEN; i++) {
1306 struct osmo_cell_global_id *enc_id;
1307 struct osmo_cell_global_id *dec_id;
1308 enc_id = &enc_cil.id_list[i].global;
1309 dec_id = &dec_cil.id_list[i].global;
1310 OSMO_ASSERT(osmo_plmn_cmp(&enc_id->lai.plmn, &dec_id->lai.plmn) == 0);
1311 OSMO_ASSERT(enc_id->lai.lac == dec_id->lai.lac);
1312 OSMO_ASSERT(enc_id->cell_identity == dec_id->cell_identity);
1313 }
1314
1315 msgb_free(msg);
1316}
1317
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001318static void print_cil(const struct gsm0808_cell_id_list2 *cil)
1319{
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001320 printf(" cell_id_list == %s\n", gsm0808_cell_id_list_name(cil));
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001321}
1322
1323void test_cell_id_list_add() {
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001324 size_t zu;
1325
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001326 const struct gsm0808_cell_id_list2 cgi1 = {
1327 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1328 .id_list_len = 1,
1329 .id_list = {
1330 {
1331 .global = {
1332 .lai = {
1333 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = false },
1334 .lac = 3,
1335 },
1336 .cell_identity = 4,
1337 }
1338 },
1339 },
1340 };
1341
1342 const struct gsm0808_cell_id_list2 cgi2 = {
1343 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1344 .id_list_len = 2,
1345 .id_list = {
1346 {
1347 .global = {
1348 .lai = {
1349 .plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
1350 .lac = 3,
1351 },
1352 .cell_identity = 4,
1353 }
1354 },
1355 {
1356 .global = {
1357 .lai = {
1358 .plmn = { .mcc = 5, .mnc = 6, .mnc_3_digits = true },
1359 .lac = 7,
1360 },
1361 .cell_identity = 8,
1362 }
1363 },
1364 },
1365 };
1366
1367 const struct gsm0808_cell_id_list2 cgi2a = {
1368 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1369 .id_list_len = 2,
1370 .id_list = {
1371 {
1372 .global = cgi2.id_list[0].global
1373 },
1374 {
1375 .global = {
1376 .lai = {
1377 .plmn = { .mcc = 9, .mnc = 10, .mnc_3_digits = true },
1378 .lac = 11,
1379 },
1380 .cell_identity = 12,
1381 }
1382 },
1383 },
1384 };
1385
1386 const struct gsm0808_cell_id_list2 cgi3 = {
1387 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1388 .id_list_len = 2,
1389 .id_list = {
1390 {
1391 .global = {
1392 .lai = {
1393 .plmn = { .mcc = 13, .mnc = 14, .mnc_3_digits = true },
1394 .lac = 15,
1395 },
1396 .cell_identity = 16,
1397 }
1398 },
1399 {
1400 .global = {
1401 .lai = {
1402 .plmn = { .mcc = 16, .mnc = 17, .mnc_3_digits = true },
1403 .lac = 18,
1404 },
1405 .cell_identity = 19,
1406 }
1407 },
1408 },
1409 };
1410
1411
1412 const struct gsm0808_cell_id_list2 lac1 = {
1413 .id_discr = CELL_IDENT_LAC,
1414 .id_list_len = 1,
1415 .id_list = {
1416 {
1417 .lac = 123
1418 },
1419 },
1420 };
1421
1422 const struct gsm0808_cell_id_list2 lac2 = {
1423 .id_discr = CELL_IDENT_LAC,
1424 .id_list_len = 2,
1425 .id_list = {
1426 {
1427 .lac = 456
1428 },
1429 {
1430 .lac = 789
1431 },
1432 },
1433 };
1434
1435 struct gsm0808_cell_id_list2 cil = {};
1436
1437 printf("------- %s\n", __func__);
1438
1439 print_cil(&cil);
1440
1441#define ADD_QUIET(other_cil, expect_rc) do { \
1442 int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001443 printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001444 OSMO_ASSERT(rc == expect_rc); \
1445 } while(0)
1446
1447#define ADD(other_cil, expect_rc) ADD_QUIET(other_cil, expect_rc); print_cil(&cil)
1448
1449 ADD(lac1, 1);
1450 ADD(lac1, 0);
1451 ADD(lac2, 2);
1452 ADD(lac2, 0);
1453 ADD(cil, 0);
1454 ADD(cgi1, -EINVAL);
1455
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001456 printf("* can't add to BSS list\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001457 cil.id_list_len = 0;
1458 cil.id_discr = CELL_IDENT_BSS;
1459 print_cil(&cil);
1460 ADD(lac1, -EINVAL);
1461
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001462 printf("* other types (including NO_CELL) take on new type iff empty\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001463 cil.id_list_len = 0;
1464 cil.id_discr = CELL_IDENT_NO_CELL;
1465 print_cil(&cil);
1466 ADD(cgi1, 1);
1467 ADD(cgi1, 0);
1468 ADD(cgi2, 2);
1469 ADD(cgi2, 0);
1470
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001471 printf("* test gsm0808_cell_id_list_name_buf()'s return val\n");
1472 zu = strlen(gsm0808_cell_id_list_name(&cil));
1473 printf(" strlen(gsm0808_cell_id_list_name(cil)) == %zu\n", zu);
1474 zu ++;
1475 while (1) {
1476 char buf[128] = "?";
1477 int rc;
1478 OSMO_ASSERT(zu < sizeof(buf));
1479 buf[zu] = '#';
1480 rc = gsm0808_cell_id_list_name_buf(buf, zu, &cil);
1481 printf(" gsm0808_cell_id_list_name_buf(buf, %zu, cil)) == %d \"%s\"\n",
1482 zu, rc, buf);
1483 OSMO_ASSERT(buf[zu] == '#');
1484 if (!zu)
1485 break;
1486 zu /= 2;
1487 }
1488
1489 printf("* list-full behavior\n");
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001490 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001491 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001492 ADD_QUIET(cgi2a, 1);
1493 printf("cil.id_list_len = %u\n", cil.id_list_len);
1494
1495 cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001496 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001497 ADD_QUIET(cgi3, -ENOSPC);
Neels Hofmeyra4399c82018-04-17 02:26:10 +02001498 printf("cil.id_list_len = %u\n", cil.id_list_len);
Neels Hofmeyr74663d92018-03-23 01:46:42 +01001499 ADD_QUIET(cgi2a, -ENOSPC);
1500 printf("cil.id_list_len = %u\n", cil.id_list_len);
1501
1502 printf("------- %s done\n", __func__);
1503}
1504
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02001505static void test_gsm0808_enc_dec_cell_id_lac()
1506{
1507 struct gsm0808_cell_id enc_ci = {
1508 .id_discr = CELL_IDENT_LAC,
1509 .id.lac = 0x0124,
1510 };
1511 struct gsm0808_cell_id dec_ci;
1512 struct msgb *msg;
1513 uint8_t rc_enc;
1514 int rc_dec;
1515
1516 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1517
1518 msg = msgb_alloc(1024, "output buffer");
1519 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1520 EXPECT_ENCODED("05 03 05 01 24");
1521
1522 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1523 OSMO_ASSERT(rc_dec == 3);
1524
1525 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1526 && enc_ci.id.lac == dec_ci.id.lac);
1527
1528 msgb_free(msg);
1529}
1530
1531static void test_gsm0808_enc_dec_cell_id_bss()
1532{
1533 struct gsm0808_cell_id enc_ci = {
1534 .id_discr = CELL_IDENT_BSS,
1535 };
1536 struct gsm0808_cell_id dec_ci;
1537 struct msgb *msg;
1538 uint8_t rc_enc;
1539 int rc_dec;
1540
1541 msg = msgb_alloc(1024, "output buffer");
1542 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1543 EXPECT_ENCODED("05 01 06");
1544
1545 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1546 OSMO_ASSERT(rc_dec == 1);
1547
1548 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1549
1550 msgb_free(msg);
1551}
1552
1553static void test_gsm0808_enc_dec_cell_id_no_cell()
1554{
1555 struct gsm0808_cell_id enc_ci = {
1556 .id_discr = CELL_IDENT_NO_CELL,
1557 };
1558 struct gsm0808_cell_id dec_ci;
1559 struct msgb *msg;
1560 uint8_t rc_enc;
1561 int rc_dec;
1562
1563 msg = msgb_alloc(1024, "output buffer");
1564 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1565 EXPECT_ENCODED("05 01 03");
1566
1567 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1568 OSMO_ASSERT(rc_dec == 1);
1569
1570 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr);
1571
1572 msgb_free(msg);
1573}
1574
1575static void test_gsm0808_enc_dec_cell_id_lai_and_lac()
1576{
1577 struct gsm0808_cell_id enc_ci = {
1578 .id_discr = CELL_IDENT_LAI_AND_LAC,
1579 .id.lai_and_lac = {
1580 .plmn = {
1581 .mcc = 123,
1582 .mnc = 456,
1583 },
1584 .lac = 0x2342,
1585 },
1586 };
1587 struct gsm0808_cell_id dec_ci;
1588 struct msgb *msg;
1589 uint8_t rc_enc;
1590 int rc_dec;
1591
1592 msg = msgb_alloc(1024, "output buffer");
1593 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1594 EXPECT_ENCODED("05 06 04 21 63 54 23 42");
1595
1596 memset(&dec_ci, 0xa5, sizeof(dec_ci));
1597 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1598 OSMO_ASSERT(rc_dec == msg->len - 2);
1599
1600 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1601 && osmo_plmn_cmp(&enc_ci.id.lai_and_lac.plmn, &dec_ci.id.lai_and_lac.plmn) == 0
1602 && enc_ci.id.lai_and_lac.lac == dec_ci.id.lai_and_lac.lac);
1603 msgb_free(msg);
1604}
1605
1606static void test_gsm0808_enc_dec_cell_id_ci()
1607{
1608 struct gsm0808_cell_id enc_ci = {
1609 .id_discr = CELL_IDENT_CI,
1610 .id.ci = 0x423,
1611 };
1612 struct gsm0808_cell_id dec_ci;
1613 struct msgb *msg;
1614 uint8_t rc_enc;
1615 int rc_dec;
1616
1617 msg = msgb_alloc(1024, "output buffer");
1618 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1619 EXPECT_ENCODED("05 03 02 04 23");
1620
1621 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1622 OSMO_ASSERT(rc_dec == msg->len - 2);
1623 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1624 && enc_ci.id.ci == dec_ci.id.ci);
1625
1626 msgb_free(msg);
1627}
1628
1629static void test_gsm0808_enc_dec_cell_id_lac_and_ci()
1630{
1631 struct gsm0808_cell_id enc_ci = {
1632 .id_discr = CELL_IDENT_LAC_AND_CI,
1633 .id.lac_and_ci = {
1634 .lac = 0x423,
1635 .ci = 0x235,
1636 },
1637 };
1638 struct gsm0808_cell_id dec_ci;
1639 struct msgb *msg;
1640 uint8_t rc_enc;
1641 int rc_dec;
1642
1643 msg = msgb_alloc(1024, "output buffer");
1644 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1645 EXPECT_ENCODED("05 05 01 04 23 02 35");
1646
1647 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1648 OSMO_ASSERT(rc_dec == msg->len - 2);
1649 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1650 && enc_ci.id.lac_and_ci.lac == dec_ci.id.lac_and_ci.lac
1651 && enc_ci.id.lac_and_ci.ci == dec_ci.id.lac_and_ci.ci);
1652
1653 msgb_free(msg);
1654}
1655
1656static void test_gsm0808_enc_dec_cell_id_global()
1657{
1658 struct gsm0808_cell_id enc_ci = {
1659 .id_discr = CELL_IDENT_WHOLE_GLOBAL,
1660 .id.global = {
1661 .lai = {
1662 .plmn = { .mcc = 123, .mnc = 456 },
1663 .lac = 0x2342
1664 },
1665 .cell_identity = 0x423,
1666 }
1667 };
1668 struct gsm0808_cell_id dec_ci;
1669 struct msgb *msg;
1670 uint8_t rc_enc;
1671 int rc_dec;
1672
1673 msg = msgb_alloc(1024, "output buffer");
1674 rc_enc = gsm0808_enc_cell_id(msg, &enc_ci);
1675 EXPECT_ENCODED("05 08 00 21 63 54 23 42 04 23");
1676
1677 rc_dec = gsm0808_dec_cell_id(&dec_ci, msg->data + 2, msg->len - 2);
1678 OSMO_ASSERT(rc_dec == msg->len - 2);
1679
1680 OSMO_ASSERT(enc_ci.id_discr == dec_ci.id_discr
1681 && osmo_plmn_cmp(&enc_ci.id.global.lai.plmn,
1682 &dec_ci.id.global.lai.plmn) == 0
1683 && enc_ci.id.global.lai.lac == dec_ci.id.global.lai.lac
1684 && enc_ci.id.global.cell_identity == dec_ci.id.global.cell_identity);
1685 msgb_free(msg);
1686}
1687
Philipp Maier5f2eb152018-09-19 13:40:21 +02001688static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg)
1689{
1690 uint16_t s15_s0;
1691
1692 printf("Input:\n");
1693 printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod);
1694 printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare);
1695 printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi);
1696 printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb);
1697 printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver);
1698 printf(" m7_95= %u\n", cfg->m7_95);
1699 printf(" m10_2= %u\n", cfg->m10_2);
1700 printf(" m12_2= %u\n", cfg->m12_2);
1701
1702 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true);
1703 printf("Result (fr):\n");
1704 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1705 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1706
1707 s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false);
1708 printf("Result (hr):\n");
1709 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1710 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1711
1712 printf("\n");
1713}
1714
1715static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void)
1716{
1717 struct gsm48_multi_rate_conf cfg;
1718
1719 printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n");
1720
1721 memset(&cfg, 0, sizeof(cfg));
1722
1723 cfg.m4_75 = 0;
1724 cfg.m5_15 = 0;
1725 cfg.m5_90 = 0;
1726 cfg.m6_70 = 0;
1727 cfg.m7_40 = 0;
1728 cfg.m7_95 = 0;
1729 cfg.m10_2 = 0;
1730 cfg.m12_2 = 0;
1731 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1732
1733 cfg.m4_75 = 1;
1734 cfg.m5_15 = 0;
1735 cfg.m5_90 = 0;
1736 cfg.m6_70 = 0;
1737 cfg.m7_40 = 0;
1738 cfg.m7_95 = 0;
1739 cfg.m10_2 = 0;
1740 cfg.m12_2 = 0;
1741 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1742
1743 cfg.m4_75 = 0;
1744 cfg.m5_15 = 1;
1745 cfg.m5_90 = 0;
1746 cfg.m6_70 = 0;
1747 cfg.m7_40 = 0;
1748 cfg.m7_95 = 0;
1749 cfg.m10_2 = 0;
1750 cfg.m12_2 = 0;
1751 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1752
1753 cfg.m4_75 = 0;
1754 cfg.m5_15 = 0;
1755 cfg.m5_90 = 1;
1756 cfg.m6_70 = 0;
1757 cfg.m7_40 = 0;
1758 cfg.m7_95 = 0;
1759 cfg.m10_2 = 0;
1760 cfg.m12_2 = 0;
1761 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1762
1763 cfg.m4_75 = 0;
1764 cfg.m5_15 = 0;
1765 cfg.m5_90 = 0;
1766 cfg.m6_70 = 1;
1767 cfg.m7_40 = 0;
1768 cfg.m7_95 = 0;
1769 cfg.m10_2 = 0;
1770 cfg.m12_2 = 0;
1771 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1772
1773 cfg.m4_75 = 0;
1774 cfg.m5_15 = 0;
1775 cfg.m5_90 = 0;
1776 cfg.m6_70 = 0;
1777 cfg.m7_40 = 1;
1778 cfg.m7_95 = 0;
1779 cfg.m10_2 = 0;
1780 cfg.m12_2 = 0;
1781 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1782
1783 cfg.m4_75 = 0;
1784 cfg.m5_15 = 0;
1785 cfg.m5_90 = 0;
1786 cfg.m6_70 = 0;
1787 cfg.m7_40 = 0;
1788 cfg.m7_95 = 1;
1789 cfg.m10_2 = 0;
1790 cfg.m12_2 = 0;
1791 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1792
1793 cfg.m4_75 = 0;
1794 cfg.m5_15 = 0;
1795 cfg.m5_90 = 0;
1796 cfg.m6_70 = 0;
1797 cfg.m7_40 = 0;
1798 cfg.m7_95 = 0;
1799 cfg.m10_2 = 1;
1800 cfg.m12_2 = 0;
1801 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1802
1803 cfg.m4_75 = 0;
1804 cfg.m5_15 = 0;
1805 cfg.m5_90 = 0;
1806 cfg.m6_70 = 0;
1807 cfg.m7_40 = 0;
1808 cfg.m7_95 = 0;
1809 cfg.m10_2 = 0;
1810 cfg.m12_2 = 1;
1811 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1812
1813 cfg.m4_75 = 1;
1814 cfg.m5_15 = 1;
1815 cfg.m5_90 = 1;
1816 cfg.m6_70 = 1;
1817 cfg.m7_40 = 0;
1818 cfg.m7_95 = 0;
1819 cfg.m10_2 = 0;
1820 cfg.m12_2 = 0;
1821 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1822
1823 cfg.m4_75 = 0;
1824 cfg.m5_15 = 0;
1825 cfg.m5_90 = 0;
1826 cfg.m6_70 = 0;
1827 cfg.m7_40 = 1;
1828 cfg.m7_95 = 1;
1829 cfg.m10_2 = 1;
1830 cfg.m12_2 = 1;
1831 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1832
1833 cfg.m4_75 = 0;
1834 cfg.m5_15 = 0;
1835 cfg.m5_90 = 1;
1836 cfg.m6_70 = 1;
1837 cfg.m7_40 = 0;
1838 cfg.m7_95 = 0;
1839 cfg.m10_2 = 1;
1840 cfg.m12_2 = 1;
1841 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1842
1843 cfg.m4_75 = 1;
1844 cfg.m5_15 = 1;
1845 cfg.m5_90 = 0;
1846 cfg.m6_70 = 0;
1847 cfg.m7_40 = 1;
1848 cfg.m7_95 = 1;
1849 cfg.m10_2 = 0;
1850 cfg.m12_2 = 0;
1851 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1852
1853 cfg.m4_75 = 0;
1854 cfg.m5_15 = 1;
1855 cfg.m5_90 = 0;
1856 cfg.m6_70 = 1;
1857 cfg.m7_40 = 0;
1858 cfg.m7_95 = 1;
1859 cfg.m10_2 = 0;
1860 cfg.m12_2 = 1;
1861 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1862
1863 cfg.m4_75 = 1;
1864 cfg.m5_15 = 0;
1865 cfg.m5_90 = 1;
1866 cfg.m6_70 = 0;
1867 cfg.m7_40 = 1;
1868 cfg.m7_95 = 0;
1869 cfg.m10_2 = 1;
1870 cfg.m12_2 = 0;
1871 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1872
1873 cfg.m4_75 = 1;
1874 cfg.m5_15 = 1;
1875 cfg.m5_90 = 1;
1876 cfg.m6_70 = 1;
1877 cfg.m7_40 = 1;
1878 cfg.m7_95 = 1;
1879 cfg.m10_2 = 1;
1880 cfg.m12_2 = 1;
1881 test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg);
1882}
1883
Philipp Maier8515d032018-09-25 15:57:49 +02001884static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0)
1885{
1886 struct gsm48_multi_rate_conf cfg;
1887
1888 printf("Input:\n");
1889 printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0,
1890 OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0));
1891
1892 gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0);
1893
1894 printf("Output:\n");
1895 printf(" m4_75= %u smod= %u\n", cfg.m4_75, cfg.smod);
1896 printf(" m5_15= %u spare= %u\n", cfg.m5_15, cfg.spare);
1897 printf(" m5_90= %u icmi= %u\n", cfg.m5_90, cfg.icmi);
1898 printf(" m6_70= %u nscb= %u\n", cfg.m6_70, cfg.nscb);
1899 printf(" m7_40= %u ver= %u\n", cfg.m7_40, cfg.ver);
1900 printf(" m7_95= %u\n", cfg.m7_95);
1901 printf(" m10_2= %u\n", cfg.m10_2);
1902 printf(" m12_2= %u\n", cfg.m12_2);
1903
1904 printf("\n");
1905}
1906
1907void test_gsm48_mr_cfg_from_gsm0808_sc_cfg()
1908{
1909 printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n");
1910
1911 /* Only one codec per setting */
1912 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1913 (GSM0808_SC_CFG_DEFAULT_AMR_4_75);
1914 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1915 (GSM0808_SC_CFG_DEFAULT_AMR_5_15);
1916 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1917 (GSM0808_SC_CFG_DEFAULT_AMR_5_90);
1918 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1919 (GSM0808_SC_CFG_DEFAULT_AMR_6_70);
1920 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1921 (GSM0808_SC_CFG_DEFAULT_AMR_7_40);
1922 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1923 (GSM0808_SC_CFG_DEFAULT_AMR_7_95);
1924 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1925 (GSM0808_SC_CFG_DEFAULT_AMR_10_2);
1926 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1927 (GSM0808_SC_CFG_DEFAULT_AMR_12_2);
1928
1929 /* Combinations */
1930 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1931 (GSM0808_SC_CFG_DEFAULT_AMR_4_75 | GSM0808_SC_CFG_DEFAULT_AMR_6_70 |
1932 GSM0808_SC_CFG_DEFAULT_AMR_10_2);
1933 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1934 (GSM0808_SC_CFG_DEFAULT_AMR_10_2 | GSM0808_SC_CFG_DEFAULT_AMR_12_2 |
1935 GSM0808_SC_CFG_DEFAULT_AMR_7_40);
1936 test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single
1937 (GSM0808_SC_CFG_DEFAULT_AMR_7_95 | GSM0808_SC_CFG_DEFAULT_AMR_12_2);
1938}
1939
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02001940struct test_cell_id_matching_data {
1941 struct gsm0808_cell_id id;
1942 struct gsm0808_cell_id match_id;
1943 bool expect_match;
1944 bool expect_exact_match;
1945};
1946
1947#define lac_23 { .id_discr = CELL_IDENT_LAC, .id.lac = 23, }
1948#define lac_42 { .id_discr = CELL_IDENT_LAC, .id.lac = 42, }
1949#define ci_5 { .id_discr = CELL_IDENT_CI, .id.ci = 5, }
1950#define ci_6 { .id_discr = CELL_IDENT_CI, .id.ci = 6, }
1951#define lac_ci_23_5 { \
1952 .id_discr = CELL_IDENT_LAC_AND_CI, \
1953 .id.lac_and_ci = { .lac = 23, .ci = 5, }, \
1954 }
1955#define lac_ci_42_6 { \
1956 .id_discr = CELL_IDENT_LAC_AND_CI, \
1957 .id.lac_and_ci = { .lac = 42, .ci = 6, }, \
1958 }
1959#define lai_23_042_23 { \
1960 .id_discr = CELL_IDENT_LAI_AND_LAC, \
1961 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
1962 }
1963#define lai_23_042_42 { \
1964 .id_discr = CELL_IDENT_LAI_AND_LAC, \
1965 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
1966 }
1967#define lai_23_99_23 { \
1968 .id_discr = CELL_IDENT_LAI_AND_LAC, \
1969 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
1970 }
1971#define lai_23_42_23 { \
1972 .id_discr = CELL_IDENT_LAI_AND_LAC, \
1973 .id.lai_and_lac = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = false }, .lac = 23, }, \
1974 }
1975#define cgi_23_042_23_5 { \
1976 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
1977 .id.global = { \
1978 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 23, }, \
1979 .cell_identity = 5, \
1980 }, \
1981 }
1982#define cgi_23_042_42_6 { \
1983 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
1984 .id.global = { \
1985 .lai = { .plmn = { .mcc = 23, .mnc = 42, .mnc_3_digits = true }, .lac = 42, }, \
1986 .cell_identity = 6, \
1987 }, \
1988 }
1989#define cgi_23_99_23_5 { \
1990 .id_discr = CELL_IDENT_WHOLE_GLOBAL, \
1991 .id.global = { \
1992 .lai = { .plmn = { .mcc = 23, .mnc = 99, .mnc_3_digits = false }, .lac = 23, }, \
1993 .cell_identity = 5, \
1994 }, \
1995 }
1996
1997
1998static const struct test_cell_id_matching_data test_cell_id_matching_tests[] = {
1999 { .id = lac_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = true },
2000 { .id = lac_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2001 { .id = lac_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2002 { .id = lac_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2003 { .id = lac_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2004 { .id = lac_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2005 { .id = lac_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2006 { .id = lac_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2007 { .id = lac_23, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2008 { .id = lac_23, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2009 { .id = lac_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2010 { .id = lac_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2011 { .id = lac_23, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2012 { .id = ci_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2013 { .id = ci_5, .match_id = lac_42, .expect_match = true, .expect_exact_match = false },
2014 { .id = ci_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = true },
2015 { .id = ci_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2016 { .id = ci_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2017 { .id = ci_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2018 { .id = ci_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2019 { .id = ci_5, .match_id = lai_23_042_42, .expect_match = true, .expect_exact_match = false },
2020 { .id = ci_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2021 { .id = ci_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2022 { .id = ci_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2023 { .id = ci_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2024 { .id = ci_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2025 { .id = lac_ci_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2026 { .id = lac_ci_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2027 { .id = lac_ci_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2028 { .id = lac_ci_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2029 { .id = lac_ci_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = true },
2030 { .id = lac_ci_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2031 { .id = lac_ci_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2032 { .id = lac_ci_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2033 { .id = lac_ci_23_5, .match_id = lai_23_99_23, .expect_match = true, .expect_exact_match = false },
2034 { .id = lac_ci_23_5, .match_id = lai_23_42_23, .expect_match = true, .expect_exact_match = false },
2035 { .id = lac_ci_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2036 { .id = lac_ci_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2037 { .id = lac_ci_23_5, .match_id = cgi_23_99_23_5, .expect_match = true, .expect_exact_match = false },
2038 { .id = lai_23_042_23, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2039 { .id = lai_23_042_23, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2040 { .id = lai_23_042_23, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2041 { .id = lai_23_042_23, .match_id = ci_6, .expect_match = true, .expect_exact_match = false },
2042 { .id = lai_23_042_23, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2043 { .id = lai_23_042_23, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2044 { .id = lai_23_042_23, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = true },
2045 { .id = lai_23_042_23, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2046 { .id = lai_23_042_23, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2047 { .id = lai_23_042_23, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2048 { .id = lai_23_042_23, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = false },
2049 { .id = lai_23_042_23, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2050 { .id = lai_23_042_23, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2051 { .id = cgi_23_042_23_5, .match_id = lac_23, .expect_match = true, .expect_exact_match = false },
2052 { .id = cgi_23_042_23_5, .match_id = lac_42, .expect_match = false, .expect_exact_match = false },
2053 { .id = cgi_23_042_23_5, .match_id = ci_5, .expect_match = true, .expect_exact_match = false },
2054 { .id = cgi_23_042_23_5, .match_id = ci_6, .expect_match = false, .expect_exact_match = false },
2055 { .id = cgi_23_042_23_5, .match_id = lac_ci_23_5, .expect_match = true, .expect_exact_match = false },
2056 { .id = cgi_23_042_23_5, .match_id = lac_ci_42_6, .expect_match = false, .expect_exact_match = false },
2057 { .id = cgi_23_042_23_5, .match_id = lai_23_042_23, .expect_match = true, .expect_exact_match = false },
2058 { .id = cgi_23_042_23_5, .match_id = lai_23_042_42, .expect_match = false, .expect_exact_match = false },
2059 { .id = cgi_23_042_23_5, .match_id = lai_23_99_23, .expect_match = false, .expect_exact_match = false },
2060 { .id = cgi_23_042_23_5, .match_id = lai_23_42_23, .expect_match = false, .expect_exact_match = false },
2061 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_23_5, .expect_match = true, .expect_exact_match = true },
2062 { .id = cgi_23_042_23_5, .match_id = cgi_23_042_42_6, .expect_match = false, .expect_exact_match = false },
2063 { .id = cgi_23_042_23_5, .match_id = cgi_23_99_23_5, .expect_match = false, .expect_exact_match = false },
2064};
2065
2066static void test_cell_id_matching()
2067{
2068 int i;
2069 bool ok = true;
2070 printf("\n%s\n", __func__);
2071
2072 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2073 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2074 int exact_match;
2075
2076 for (exact_match = 0; exact_match < 2; exact_match++) {
2077 bool result;
2078 bool expect_result = exact_match ? d->expect_exact_match : d->expect_match;
2079
2080 result = gsm0808_cell_ids_match(&d->id, &d->match_id, (bool)exact_match);
2081
2082 printf("[%d] %s %s %s%s\n",
2083 i,
2084 gsm0808_cell_id_name(&d->id),
2085 gsm0808_cell_id_name2(&d->match_id),
2086 result ? "MATCH" : "don't match",
2087 exact_match ? " exactly" : "");
2088 if (result != expect_result) {
2089 printf(" ERROR: expected %s\n", d->expect_match ? "MATCH" : "no match");
2090 ok = false;
2091 }
2092 }
2093 }
2094
2095 OSMO_ASSERT(ok);
2096}
2097
2098static bool test_cell_id_list_matching_discrs(bool test_match,
2099 enum CELL_IDENT id_discr,
2100 enum CELL_IDENT list_discr)
2101{
2102 int i, j;
2103 const struct gsm0808_cell_id *id = NULL;
2104 struct gsm0808_cell_id_list2 list = {};
2105 int match_idx = -1;
2106 int result;
2107
2108 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2109 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2110 if (id_discr != d->id.id_discr)
2111 continue;
2112 id = &d->id;
2113 break;
2114 }
2115
2116 if (!id) {
2117 printf("Did not find any entry for %s\n", gsm0808_cell_id_discr_name(id_discr));
2118 return true;
2119 }
2120
2121 /* Collect those entries with exactly this id on the left, of type list_discr on the right.
2122 * Collect the mismatches first, for more interesting match indexes in the results. */
2123 for (j = 0; j < 2; j++) {
2124 bool collect_matches = (bool)j;
2125
2126 /* If we want to have a mismatching list, don't add any entries that match. */
2127 if (!test_match && collect_matches)
2128 continue;
2129
2130 for (i = 0; i < ARRAY_SIZE(test_cell_id_matching_tests); i++) {
2131 const struct test_cell_id_matching_data *d = &test_cell_id_matching_tests[i];
2132 struct gsm0808_cell_id_list2 add;
2133
2134 /* Ignore those with a different d->id */
2135 if (!gsm0808_cell_ids_match(&d->id, id, true))
2136 continue;
2137
2138 /* Ignore those with a different d->match_id discr */
2139 if (d->match_id.id_discr != list_discr)
2140 continue;
2141
2142 if (collect_matches != d->expect_match)
2143 continue;
2144
2145 if (match_idx < 0 && d->expect_match) {
2146 match_idx = list.id_list_len;
2147 }
2148
2149 gsm0808_cell_id_to_list(&add, &d->match_id);
2150 gsm0808_cell_id_list_add(&list, &add);
2151 }
2152 }
2153
2154 if (!list.id_list_len) {
2155 printf("%s vs. %s: No match_id entries to test %s\n",
2156 gsm0808_cell_id_name(id),
2157 gsm0808_cell_id_discr_name(list_discr),
2158 test_match ? "MATCH" : "mismatch");
2159 return true;
2160 }
2161
2162 result = gsm0808_cell_id_matches_list(id, &list, 0, false);
2163
2164 printf("%s and %s: ",
2165 gsm0808_cell_id_name(id),
2166 gsm0808_cell_id_list_name(&list));
2167 if (result >= 0)
2168 printf("MATCH at [%d]\n", result);
2169 else
2170 printf("mismatch\n");
2171
2172 if (test_match
2173 && (result < 0 || result != match_idx)) {
2174 printf(" ERROR: expected MATCH at %d\n", match_idx);
2175 return false;
2176 }
2177
2178 if (!test_match && result >= 0) {
2179 printf(" ERROR: expected mismatch\n");
2180 return false;
2181 }
2182
2183 return true;
2184}
2185
2186static void test_cell_id_list_matching(bool test_match)
2187{
2188 int i, j;
2189 bool ok = true;
2190
2191 const enum CELL_IDENT discrs[] = {
2192 CELL_IDENT_LAC, CELL_IDENT_CI, CELL_IDENT_LAC_AND_CI, CELL_IDENT_LAI_AND_LAC,
2193 CELL_IDENT_WHOLE_GLOBAL,
2194 };
2195
2196 printf("\n%s(%s)\n", __func__, test_match ? "test match" : "test mismatch");
2197
2198 /* Autogenerate Cell ID lists from above dataset, which should match / not match. */
2199 for (i = 0; i < ARRAY_SIZE(discrs); i++) {
2200 for (j = 0; j < ARRAY_SIZE(discrs); j++)
2201 if (!test_cell_id_list_matching_discrs(test_match,
2202 discrs[i], discrs[j]))
2203 ok = false;
2204 }
2205
2206 OSMO_ASSERT(ok);
2207}
2208
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002209int main(int argc, char **argv)
2210{
Max969fb2e2018-12-10 11:01:10 +01002211 void *ctx = talloc_named_const(NULL, 0, "gsm0808 test");
2212 msgb_talloc_ctx_init(ctx, 0);
2213 osmo_init_logging2(ctx, NULL);
2214
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002215 printf("Testing generation of GSM0808 messages\n");
Philipp Maier4f4905f2018-11-30 13:36:12 +01002216 test_gsm0808_enc_cause();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002217 test_create_layer3();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002218 test_create_layer3_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002219 test_create_reset();
Philipp Maier15596e22017-04-05 17:55:27 +02002220 test_create_reset_ack();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002221 test_create_clear_command();
2222 test_create_clear_complete();
Philipp Maierb478dd32017-03-29 15:50:05 +02002223 test_create_cipher();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002224 test_create_cipher_complete();
2225 test_create_cipher_reject();
Maxed651d22018-11-07 15:25:05 +01002226 test_create_cipher_reject_ext();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002227 test_create_cm_u();
2228 test_create_sapi_reject();
Philipp Maierc6144a22017-03-29 17:53:43 +02002229 test_create_ass();
Max52074322018-11-30 10:44:07 +01002230 test_create_ass2();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002231 test_create_ass_compl();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002232 test_create_ass_compl_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002233 test_create_ass_fail();
Philipp Maierfa896ab2017-03-27 16:55:32 +02002234 test_create_ass_fail_aoip();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002235 test_create_clear_rqst();
Philipp Maier3d48ec02017-03-29 17:37:55 +02002236 test_create_paging();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002237 test_create_dtap();
2238 test_prepend_dtap();
Max969fb2e2018-12-10 11:01:10 +01002239
Max47022152018-12-19 18:51:00 +01002240 test_enc_dec_lcls();
Max969fb2e2018-12-10 11:01:10 +01002241
Philipp Maier22401432017-03-24 17:59:26 +01002242 test_enc_dec_aoip_trasp_addr_v4();
2243 test_enc_dec_aoip_trasp_addr_v6();
Philipp Maier6f725d62017-03-24 18:03:17 +01002244 test_gsm0808_enc_dec_speech_codec();
Philipp Maier6f725d62017-03-24 18:03:17 +01002245 test_gsm0808_enc_dec_speech_codec_ext_with_cfg();
Philipp Maierbb839662017-06-01 17:11:19 +02002246 test_gsm0808_enc_dec_speech_codec_with_cfg();
Philipp Maier6f725d62017-03-24 18:03:17 +01002247 test_gsm0808_enc_dec_speech_codec_list();
Philipp Maierf6c369f2018-10-16 15:24:47 +02002248 test_gsm0808_enc_dec_empty_speech_codec_list();
Philipp Maiere0c65302017-03-28 17:05:40 +02002249 test_gsm0808_enc_dec_channel_type();
Philipp Maier14e76b92017-03-28 18:36:52 +02002250 test_gsm0808_enc_dec_encrypt_info();
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002251
Philipp Maier783047e2017-03-29 11:35:50 +02002252 test_gsm0808_enc_dec_cell_id_list_lac();
2253 test_gsm0808_enc_dec_cell_id_list_single_lac();
Stefan Sperlinge1a86742018-03-15 18:05:02 +01002254 test_gsm0808_enc_dec_cell_id_list_multi_lac();
Philipp Maier783047e2017-03-29 11:35:50 +02002255 test_gsm0808_enc_dec_cell_id_list_bss();
Stefan Sperling23381452018-03-15 19:38:15 +01002256 test_gsm0808_enc_dec_cell_id_list_multi_lai_and_lac();
Stefan Sperling9c62fc62018-03-16 10:23:34 +01002257 test_gsm0808_enc_dec_cell_id_list_multi_ci();
Stefan Sperlinged4327c2018-03-16 11:02:59 +01002258 test_gsm0808_enc_dec_cell_id_list_multi_lac_and_ci();
Stefan Sperling483f3862018-03-16 12:21:26 +01002259 test_gsm0808_enc_dec_cell_id_list_multi_global();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002260
Neels Hofmeyr74663d92018-03-23 01:46:42 +01002261 test_cell_id_list_add();
2262
Neels Hofmeyr250e7f72018-04-13 03:30:14 +02002263 test_gsm0808_enc_dec_cell_id_lac();
2264 test_gsm0808_enc_dec_cell_id_bss();
2265 test_gsm0808_enc_dec_cell_id_no_cell();
2266 test_gsm0808_enc_dec_cell_id_lai_and_lac();
2267 test_gsm0808_enc_dec_cell_id_ci();
2268 test_gsm0808_enc_dec_cell_id_lac_and_ci();
2269 test_gsm0808_enc_dec_cell_id_global();
2270
Philipp Maier5f2eb152018-09-19 13:40:21 +02002271 test_gsm0808_sc_cfg_from_gsm48_mr_cfg();
Philipp Maier8515d032018-09-25 15:57:49 +02002272 test_gsm48_mr_cfg_from_gsm0808_sc_cfg();
Philipp Maier5f2eb152018-09-19 13:40:21 +02002273
Neels Hofmeyrd01ef752018-09-21 15:57:26 +02002274 test_cell_id_matching();
2275 test_cell_id_list_matching(true);
2276 test_cell_id_list_matching(false);
2277
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01002278 printf("Done\n");
2279 return EXIT_SUCCESS;
2280}