blob: 2049e9f8ee7f8042b2a22016cf9f6dec1538af9e [file] [log] [blame]
Neels Hofmeyrf8178142017-01-25 15:04:16 +01001/* Osmocom MSC+VLR end-to-end tests */
2
3/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 *
5 * All Rights Reserved
6 *
7 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <getopt.h>
25#include <stdlib.h>
26
27#include <osmocom/core/logging.h>
28#include <osmocom/core/utils.h>
29#include <osmocom/core/msgb.h>
30#include <osmocom/core/application.h>
31#include <osmocom/gsm/protocol/gsm_04_11.h>
32#include <osmocom/gsm/gsup.h>
33#include <openbsc/gsup_client.h>
34#include <openbsc/gsm_04_11.h>
35#include <openbsc/bsc_subscriber.h>
36#include <openbsc/debug.h>
Neels Hofmeyra1756f32016-05-20 21:59:55 +020037#include <openbsc/iu.h>
38#include <openbsc/iucs_ranap.h>
Neels Hofmeyrf8178142017-01-25 15:04:16 +010039
40#include "msc_vlr_tests.h"
41
42bool _log_lines = false;
43
44struct gsm_network *net = NULL;
45
46struct gsm_bts *the_bts;
47
48const char *gsup_tx_expected = NULL;
49bool gsup_tx_confirmed;
50
51struct msgb *dtap_tx_expected = NULL;
52bool dtap_tx_confirmed;
53
54enum result_sent lu_result_sent;
55enum result_sent cm_service_result_sent;
56bool auth_request_sent;
57const char *auth_request_expect_rand;
58const char *auth_request_expect_autn;
59bool cipher_mode_cmd_sent;
60bool cipher_mode_cmd_sent_with_imeisv;
61
62struct msgb *msgb_from_hex(const char *label, uint16_t size, const char *hex)
63{
64 struct msgb *msg = msgb_alloc(size, label);
65 unsigned char *rc;
66 msg->l2h = msg->head;
67 rc = msgb_put(msg, osmo_hexparse(hex, msg->head, msgb_tailroom(msg)));
68 OSMO_ASSERT(rc == msg->l2h);
69 return msg;
70}
71
72void dtap_expect_tx(const char *hex)
73{
Neels Hofmeyra1756f32016-05-20 21:59:55 +020074 /* Has the previously expected dtap been received? */
Neels Hofmeyrf8178142017-01-25 15:04:16 +010075 OSMO_ASSERT(!dtap_tx_expected);
76 if (!hex)
77 return;
78 dtap_tx_expected = msgb_from_hex("dtap_tx_expected", 1024, hex);
79 dtap_tx_confirmed = false;
80}
81
82void dtap_expect_tx_ussd(char *ussd_text)
83{
84 uint8_t ussd_enc[128];
85 int len;
86 /* header */
87 char ussd_msg_hex[128] = "8b2a1c27a225020100302002013b301b04010f0416";
88
89 log("expecting USSD:\n %s", ussd_text);
90 /* append encoded USSD text */
91 gsm_7bit_encode_n_ussd(ussd_enc, sizeof(ussd_enc), ussd_text,
92 &len);
93 strncat(ussd_msg_hex, osmo_hexdump_nospc(ussd_enc, len),
94 sizeof(ussd_msg_hex) - strlen(ussd_msg_hex));
95 dtap_expect_tx(ussd_msg_hex);
96}
97
98int vlr_gsupc_read_cb(struct gsup_client *gsupc, struct msgb *msg);
99
100void gsup_rx(const char *rx_hex, const char *expect_tx_hex)
101{
102 int rc;
103 struct msgb *msg;
104 const char *label;
105
106 gsup_expect_tx(expect_tx_hex);
107
108 msg = msgb_from_hex("gsup", 1024, rx_hex);
109 label = osmo_gsup_message_type_name(msg->l2h[0]);
110 fprintf(stderr, "<-- GSUP rx %s: %s\n", label,
111 osmo_hexdump_nospc(msgb_l2(msg), msgb_l2len(msg)));
112 rc = vlr_gsupc_read_cb(net->vlr->gsup_client, msg);
113 fprintf(stderr, "<-- GSUP rx %s: vlr_gsupc_read_cb() returns %d\n",
114 label, rc);
115 if (expect_tx_hex)
116 OSMO_ASSERT(gsup_tx_confirmed);
117 talloc_free(msg);
118}
119
120bool conn_exists(struct gsm_subscriber_connection *conn)
121{
122 struct gsm_subscriber_connection *c;
123 llist_for_each_entry(c, &net->subscr_conns, entry) {
124 if (c == conn)
125 return true;
126 }
127 return false;
128}
129
130enum ran_type rx_from_ran = RAN_GERAN_A;
131
132struct gsm_subscriber_connection *conn_new(void)
133{
134 struct gsm_subscriber_connection *conn;
135 conn = msc_subscr_con_allocate(net);
136 conn->bts = the_bts;
137 conn->via_ran = rx_from_ran;
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200138 if (conn->via_ran == RAN_UTRAN_IU) {
139 struct ue_conn_ctx *ue_ctx = talloc_zero(conn, struct ue_conn_ctx);
140 *ue_ctx = (struct ue_conn_ctx){
141 .link = (void*)0x23,
142 .conn_id = 42,
143 };
144 conn->iu.ue_ctx = ue_ctx;
145 }
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100146 return conn;
147}
148
149struct gsm_subscriber_connection *g_conn = NULL;
150
151void rx_from_ms(struct msgb *msg)
152{
153 int rc;
154
155 struct gsm48_hdr *gh = msgb_l3(msg);
156 log("rx from MS: pdisc=0x%02x msg_type=0x%02x",
157 gh->proto_discr, gh->msg_type);
158
159 if (g_conn && !conn_exists(g_conn))
160 g_conn = NULL;
161
162 if (!g_conn) {
163 log("new conn");
164 g_conn = conn_new();
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200165 rc = msc_compl_l3(g_conn, msg, 23);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100166 if (rc == BSC_API_CONN_POL_REJECT) {
167 msc_subscr_con_free(g_conn);
168 g_conn = NULL;
169 }
170 } else {
171 if ((gsm48_hdr_pdisc(gh) == GSM48_PDISC_RR)
172 && (gsm48_hdr_msg_type(gh) == GSM48_MT_RR_CIPH_M_COMPL))
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200173 msc_cipher_mode_compl(g_conn, msg, 0);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100174 else
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200175 msc_dtap(g_conn, 23, msg);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100176 }
177
178 if (g_conn && !conn_exists(g_conn))
179 g_conn = NULL;
180}
181
182void ms_sends_msg(const char *hex)
183{
184 struct msgb *msg;
185
186 msg = msgb_from_hex("ms_sends_msg", 1024, hex);
187 msg->l1h = msg->l2h = msg->l3h = msg->data;
188 rx_from_ms(msg);
189 talloc_free(msg);
190}
191
192int ms_sends_msg_fake(uint8_t pdisc, uint8_t msg_type)
193{
194 int rc;
195 struct msgb *msg;
196 struct gsm48_hdr *gh;
197
198 msg = msgb_alloc(1024, "ms_sends_msg_fake");
199 msg->l1h = msg->l2h = msg->l3h = msg->data;
200
201 gh = (struct gsm48_hdr*)msgb_put(msg, sizeof(*gh));
202 gh->proto_discr = pdisc;
203 gh->msg_type = msg_type;
204 /* some amount of data, whatever */
205 msgb_put(msg, 123);
206
207 rc = gsm0408_dispatch(g_conn, msg);
208
209 talloc_free(msg);
210 return rc;
211}
212
213void thwart_rx_non_initial_requests()
214{
215 log("requests shall be thwarted");
216 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_CC, GSM48_MT_CC_SETUP) == -EACCES);
217 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_MM, 0x33 /* nonexistent */) == -EACCES);
218 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_RR, GSM48_MT_RR_SYSINFO_1) == -EACCES);
219 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_SMS, GSM411_MT_CP_DATA) == -EACCES);
220}
221
222void send_sms(struct vlr_subscr *receiver,
223 struct vlr_subscr *sender,
224 char *str)
225{
226 struct gsm_sms *sms = sms_from_text(receiver, sender, 0, str);
227 gsm411_send_sms_subscr(receiver, sms);
228}
229
230unsigned char next_rand_byte = 0;
231/* override, requires '-Wl,--wrap=RAND_bytes' */
232int __real_RAND_bytes(unsigned char *buf, int num);
233int __wrap_RAND_bytes(unsigned char *buf, int num)
234{
235 int i;
236 for (i = 0; i < num; i++)
237 buf[i] = next_rand_byte++;
238 return 1;
239}
240
241/* override, requires '-Wl,--wrap=gsm340_gen_scts' */
242void __real_gsm340_gen_scts(uint8_t *scts, time_t time);
243void __wrap_gsm340_gen_scts(uint8_t *scts, time_t time)
244{
Neels Hofmeyr81512492017-08-22 18:06:42 +0200245 /* Write fixed time bytes for deterministic test results */
246 osmo_hexparse("07101000000000", scts, 7);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100247}
248
249const char *paging_expecting_imsi = NULL;
250uint32_t paging_expecting_tmsi;
251bool paging_sent;
252bool paging_stopped;
253
254void paging_expect_imsi(const char *imsi)
255{
256 paging_expecting_imsi = imsi;
257 paging_expecting_tmsi = GSM_RESERVED_TMSI;
258}
259
260void paging_expect_tmsi(uint32_t tmsi)
261{
262 paging_expecting_tmsi = tmsi;
263 paging_expecting_imsi = NULL;
264}
265
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200266int _paging_sent(enum ran_type via_ran, const char *imsi, uint32_t tmsi, uint32_t lac)
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100267{
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200268 log("%s sends out paging request to IMSI %s, TMSI 0x%08x, LAC %u",
269 ran_type_name(via_ran), imsi, tmsi, lac);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100270 OSMO_ASSERT(paging_expecting_imsi || (paging_expecting_tmsi != GSM_RESERVED_TMSI));
271 if (paging_expecting_imsi)
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200272 VERBOSE_ASSERT(strcmp(paging_expecting_imsi, imsi), == 0, "%d");
273 if (paging_expecting_tmsi != GSM_RESERVED_TMSI) {
274 VERBOSE_ASSERT(paging_expecting_tmsi, == tmsi, "0x%08x");
275 }
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100276 paging_sent = true;
277 paging_stopped = false;
278 return 1;
279}
280
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200281/* override, requires '-Wl,--wrap=iu_page_cs' */
282int __real_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac);
283int __wrap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
284{
285 return _paging_sent(RAN_UTRAN_IU, imsi, tmsi ? *tmsi : GSM_RESERVED_TMSI, lac);
286}
287
288/* override, requires '-Wl,--wrap=a_page' */
289int __real_a_page(const char *imsi, uint32_t tmsi, uint16_t lac);
290int __wrap_a_page(const char *imsi, uint32_t tmsi, uint16_t lac)
291{
292 return _paging_sent(RAN_GERAN_A, imsi, tmsi, lac);
293}
294
295/* override, requires '-Wl,--wrap=msc_stop_paging' */
296void __real_msc_stop_paging(struct vlr_subscr *vsub);
297void __wrap_msc_stop_paging(struct vlr_subscr *vsub)
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100298{
299 paging_stopped = true;
300}
301
302void clear_vlr()
303{
304 struct vlr_subscr *vsub, *n;
305 llist_for_each_entry_safe(vsub, n, &net->vlr->subscribers, list) {
306 vlr_subscr_free(vsub);
307 }
308
309 net->authentication_required = false;
310 net->a5_encryption = VLR_CIPH_NONE;
311 net->vlr->cfg.check_imei_rqd = false;
312 net->vlr->cfg.assign_tmsi = false;
Neels Hofmeyr2d503d02017-07-18 15:39:27 +0200313 net->vlr->cfg.retrieve_imeisv_early = false;
314 net->vlr->cfg.retrieve_imeisv_ciphered = false;
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100315
316 rx_from_ran = RAN_GERAN_A;
317 auth_request_sent = false;
318 auth_request_expect_rand = NULL;
319 auth_request_expect_autn = NULL;
320
321 next_rand_byte = 0;
322
323 osmo_gettimeofday_override = false;
324}
325
326static struct log_info_cat test_categories[] = {
327 [DMSC] = {
328 .name = "DMSC",
329 .description = "Mobile Switching Center",
330 .enabled = 1, .loglevel = LOGL_DEBUG,
331 },
332 [DRLL] = {
333 .name = "DRLL",
334 .description = "A-bis Radio Link Layer (RLL)",
335 .enabled = 1, .loglevel = LOGL_DEBUG,
336 },
337 [DMM] = {
338 .name = "DMM",
339 .description = "Layer3 Mobility Management (MM)",
340 .enabled = 1, .loglevel = LOGL_DEBUG,
341 },
342 [DRR] = {
343 .name = "DRR",
344 .description = "Layer3 Radio Resource (RR)",
345 .enabled = 1, .loglevel = LOGL_DEBUG,
346 },
347 [DCC] = {
348 .name = "DCC",
349 .description = "Layer3 Call Control (CC)",
350 .enabled = 1, .loglevel = LOGL_NOTICE,
351 },
352 [DMM] = {
353 .name = "DMM",
354 .description = "Layer3 Mobility Management (MM)",
355 .enabled = 1, .loglevel = LOGL_DEBUG,
356 },
357 [DVLR] = {
358 .name = "DVLR",
359 .description = "Visitor Location Register",
360 .enabled = 1, .loglevel = LOGL_DEBUG,
361 },
362 [DREF] = {
363 .name = "DREF",
364 .description = "Reference Counting",
365 .enabled = 1, .loglevel = LOGL_DEBUG,
366 },
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200367 [DPAG] = {
368 .name = "DPAG",
369 .description = "Paging Subsystem",
370 .enabled = 1, .loglevel = LOGL_DEBUG,
371 },
372 [DIUCS] = {
373 .name = "DIUCS",
374 .description = "Iu-CS Protocol",
375 .enabled = 1, .loglevel = LOGL_DEBUG,
376 },
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100377};
378
379static struct log_info info = {
380 .cat = test_categories,
381 .num_cat = ARRAY_SIZE(test_categories),
382};
383
384extern void *tall_bsc_ctx;
385
386int fake_mncc_recv(struct gsm_network *net, struct msgb *msg)
387{
388 fprintf(stderr, "rx MNCC\n");
389 return 0;
390}
391
392/* override, requires '-Wl,--wrap=gsup_client_create' */
393struct gsup_client *
394__real_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
395 gsup_client_read_cb_t read_cb,
396 struct oap_client_config *oap_config);
397struct gsup_client *
398__wrap_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
399 gsup_client_read_cb_t read_cb,
400 struct oap_client_config *oap_config)
401{
402 struct gsup_client *gsupc;
403 gsupc = talloc_zero(tall_bsc_ctx, struct gsup_client);
404 OSMO_ASSERT(gsupc);
405 return gsupc;
406}
407
408/* override, requires '-Wl,--wrap=gsup_client_send' */
409int __real_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
410int __wrap_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
411{
412 const char *is = osmo_hexdump_nospc(msg->data, msg->len);
413 fprintf(stderr, "GSUP --> HLR: %s: %s\n",
414 osmo_gsup_message_type_name(msg->data[0]), is);
415
416 OSMO_ASSERT(gsup_tx_expected);
417 if (strcmp(gsup_tx_expected, is)) {
418 fprintf(stderr, "Mismatch! Expected:\n%s\n", gsup_tx_expected);
419 abort();
420 }
421
422 talloc_free(msg);
423 gsup_tx_confirmed = true;
424 gsup_tx_expected = NULL;
425 return 0;
426}
427
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200428int _validate_dtap(struct msgb *msg, enum ran_type to_ran)
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100429{
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200430 btw("DTAP --%s--> MS: %s",
431 ran_type_name(to_ran),
432 osmo_hexdump_nospc(msg->data, msg->len));
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100433
434 OSMO_ASSERT(dtap_tx_expected);
435 if (msg->len != dtap_tx_expected->len
436 || memcmp(msg->data, dtap_tx_expected->data, msg->len)) {
437 fprintf(stderr, "Mismatch! Expected:\n%s\n",
438 osmo_hexdump_nospc(dtap_tx_expected->data,
439 dtap_tx_expected->len));
440 abort();
441 }
442
443 btw("DTAP matches expected message");
444
445 talloc_free(msg);
446 dtap_tx_confirmed = true;
447 talloc_free(dtap_tx_expected);
448 dtap_tx_expected = NULL;
449 return 0;
450}
451
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200452/* override, requires '-Wl,--wrap=iu_tx' */
453int __real_iu_tx(struct msgb *msg, uint8_t sapi);
454int __wrap_iu_tx(struct msgb *msg, uint8_t sapi)
455{
456 return _validate_dtap(msg, RAN_UTRAN_IU);
457}
458
459/* override, requires '-Wl,--wrap=iu_tx_release' */
460int __real_iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause);
461int __wrap_iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
462{
463 btw("Iu Release --%s--> MS", ran_type_name(RAN_UTRAN_IU));
464 return 0;
465}
466
467/* override, requires '-Wl,--wrap=iu_tx_common_id' */
468int __real_iu_tx_common_id(struct ue_conn_ctx *ue_ctx, const char *imsi);
469int __wrap_iu_tx_common_id(struct ue_conn_ctx *ue_ctx, const char *imsi)
470{
471 btw("Iu Common ID --%s--> MS (IMSI=%s)", ran_type_name(RAN_UTRAN_IU), imsi);
472 return 0;
473}
474
475/* override, requires '-Wl,--wrap=a_tx' */
476int __real_a_tx(struct msgb *msg, uint8_t sapi);
477int __wrap_a_tx(struct msgb *msg, uint8_t sapi)
478{
479 return _validate_dtap(msg, RAN_GERAN_A);
480}
481
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100482static int fake_vlr_tx_lu_acc(void *msc_conn_ref, uint32_t send_tmsi)
483{
484 struct gsm_subscriber_connection *conn = msc_conn_ref;
485 if (send_tmsi == GSM_RESERVED_TMSI)
486 btw("sending LU Accept for %s", vlr_subscr_name(conn->vsub));
487 else
488 btw("sending LU Accept for %s, with TMSI 0x%08x",
489 vlr_subscr_name(conn->vsub), send_tmsi);
490 lu_result_sent |= RES_ACCEPT;
491 return 0;
492}
493
494static int fake_vlr_tx_lu_rej(void *msc_conn_ref, uint8_t cause)
495{
496 struct gsm_subscriber_connection *conn = msc_conn_ref;
497 btw("sending LU Reject for %s, cause %u", vlr_subscr_name(conn->vsub), cause);
498 lu_result_sent |= RES_REJECT;
499 return 0;
500}
501
502static int fake_vlr_tx_cm_serv_acc(void *msc_conn_ref)
503{
504 struct gsm_subscriber_connection *conn = msc_conn_ref;
505 btw("sending CM Service Accept for %s", vlr_subscr_name(conn->vsub));
506 cm_service_result_sent |= RES_ACCEPT;
507 return 0;
508}
509
510static int fake_vlr_tx_cm_serv_rej(void *msc_conn_ref,
511 enum vlr_proc_arq_result result)
512{
513 struct gsm_subscriber_connection *conn = msc_conn_ref;
514 btw("sending CM Service Reject for %s, result %s",
515 vlr_subscr_name(conn->vsub),
516 vlr_proc_arq_result_name(result));
517 cm_service_result_sent |= RES_REJECT;
518 return 0;
519}
520
521static int fake_vlr_tx_auth_req(void *msc_conn_ref, struct gsm_auth_tuple *at,
522 bool send_autn)
523{
524 struct gsm_subscriber_connection *conn = msc_conn_ref;
525 char *hex;
526 bool ok = true;
527 btw("sending %s Auth Request for %s: tuple use_count=%d key_seq=%d auth_types=0x%x and...",
528 send_autn? "UMTS" : "GSM", vlr_subscr_name(conn->vsub),
529 at->use_count, at->key_seq, at->vec.auth_types);
530
531 hex = osmo_hexdump_nospc((void*)&at->vec.rand, sizeof(at->vec.rand));
532 btw("...rand=%s", hex);
533 if (!auth_request_expect_rand
534 || strcmp(hex, auth_request_expect_rand) != 0) {
535 ok = false;
536 log("FAILURE: expected rand=%s",
537 auth_request_expect_rand ? auth_request_expect_rand : "-");
538 }
539
540 if (send_autn) {
541 hex = osmo_hexdump_nospc((void*)&at->vec.autn, sizeof(at->vec.autn));
542 btw("...autn=%s", hex);
543 if (!auth_request_expect_autn
544 || strcmp(hex, auth_request_expect_autn) != 0) {
545 ok = false;
546 log("FAILURE: expected autn=%s",
547 auth_request_expect_autn ? auth_request_expect_autn : "-");
548 }
549 } else if (auth_request_expect_autn) {
550 ok = false;
551 log("FAILURE: no AUTN sent, expected AUTN = %s",
552 auth_request_expect_autn);
553 }
554
555 if (send_autn)
556 btw("...expecting res=%s",
557 osmo_hexdump_nospc((void*)&at->vec.res, at->vec.res_len));
558 else
559 btw("...expecting sres=%s",
560 osmo_hexdump_nospc((void*)&at->vec.sres, sizeof(at->vec.sres)));
561
562 auth_request_sent = ok;
563 return 0;
564}
565
566static int fake_vlr_tx_auth_rej(void *msc_conn_ref)
567{
568 struct gsm_subscriber_connection *conn = msc_conn_ref;
569 btw("sending Auth Reject for %s", vlr_subscr_name(conn->vsub));
570 return 0;
571}
572
573static int fake_vlr_tx_ciph_mode_cmd(void *msc_conn_ref, enum vlr_ciph ciph,
574 bool retrieve_imeisv)
575{
576 /* FIXME: we actually would like to see the message bytes checked here,
577 * not possible while msc_vlr_set_ciph_mode() calls
578 * gsm0808_cipher_mode() directly. When the MSCSPLIT is ready, check
579 * the tx bytes in the sense of dtap_expect_tx() above. */
580 struct gsm_subscriber_connection *conn = msc_conn_ref;
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200581 switch (conn->via_ran) {
582 case RAN_GERAN_A:
583 btw("sending Ciphering Mode Command for %s: cipher=%s kc=%s"
584 " retrieve_imeisv=%d",
585 vlr_subscr_name(conn->vsub),
586 vlr_ciph_name(conn->network->a5_encryption),
587 osmo_hexdump_nospc(conn->vsub->last_tuple->vec.kc, 8),
588 retrieve_imeisv);
589 break;
590 case RAN_UTRAN_IU:
591 btw("sending SecurityModeControl for %s",
592 vlr_subscr_name(conn->vsub));
593 break;
594 default:
595 btw("UNKNOWN RAN TYPE %d", conn->via_ran);
596 OSMO_ASSERT(false);
597 return -1;
598 }
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100599 cipher_mode_cmd_sent = true;
600 cipher_mode_cmd_sent_with_imeisv = retrieve_imeisv;
601 return 0;
602}
603
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200604void ms_sends_security_mode_complete()
605{
606 OSMO_ASSERT(g_conn);
607 OSMO_ASSERT(g_conn->via_ran == RAN_UTRAN_IU);
608 OSMO_ASSERT(g_conn->iu.ue_ctx);
609 msc_rx_sec_mode_compl(g_conn);
610}
611
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100612const struct timeval fake_time_start_time = { 123, 456 };
613
614void fake_time_start()
615{
616 osmo_gettimeofday_override_time = fake_time_start_time;
617 osmo_gettimeofday_override = true;
618 fake_time_passes(0, 0);
619}
620
621void check_talloc(void *msgb_ctx, void *tall_bsc_ctx, int expected_blocks)
622{
623 talloc_report_full(msgb_ctx, stderr);
624 fprintf(stderr, "talloc_total_blocks(tall_bsc_ctx) == %zu\n",
625 talloc_total_blocks(tall_bsc_ctx));
626 if (talloc_total_blocks(tall_bsc_ctx) != expected_blocks)
627 talloc_report_full(tall_bsc_ctx, stderr);
628 fprintf(stderr, "\n");
629}
630
631static struct {
632 bool verbose;
633 int run_test_nr;
634} cmdline_opts = {
635 .verbose = false,
636 .run_test_nr = -1,
637};
638
639static void print_help(const char *program)
640{
641 printf("Usage:\n"
642 " %s [-v] [N [N...]]\n"
643 "Options:\n"
644 " -h --help show this text.\n"
645 " -v --verbose print source file and line numbers\n"
646 " N run only the Nth test (first test is N=1)\n",
647 program
648 );
649}
650
651static void handle_options(int argc, char **argv)
652{
653 while (1) {
654 int option_index = 0, c;
655 static struct option long_options[] = {
656 {"help", 0, 0, 'h'},
657 {"verbose", 1, 0, 'v'},
658 {0, 0, 0, 0}
659 };
660
661 c = getopt_long(argc, argv, "hv",
662 long_options, &option_index);
663 if (c == -1)
664 break;
665
666 switch (c) {
667 case 'h':
668 print_help(argv[0]);
669 exit(0);
670 case 'v':
671 cmdline_opts.verbose = true;
672 break;
673 default:
674 /* catch unknown options *as well as* missing arguments. */
675 fprintf(stderr, "Error in command line options. Exiting.\n");
676 exit(-1);
677 break;
678 }
679 }
680}
681
682void *msgb_ctx = NULL;
683
684void run_tests(int nr)
685{
686 int test_nr;
687 nr --; /* arg's first test is 1, in here it's 0 */
688 for (test_nr = 0; msc_vlr_tests[test_nr]; test_nr ++) {
689 if (nr >= 0 && test_nr != nr)
690 continue;
691
692 if (cmdline_opts.verbose)
693 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
694
695 msc_vlr_tests[test_nr]();
696
697 if (cmdline_opts.verbose)
698 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
699
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200700 check_talloc(msgb_ctx, tall_bsc_ctx, 9);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100701 } while(0);
702}
703
704int main(int argc, char **argv)
705{
706 handle_options(argc, argv);
707
708 tall_bsc_ctx = talloc_named_const(NULL, 0, "subscr_conn_test_ctx");
709 msgb_ctx = msgb_talloc_ctx_init(tall_bsc_ctx, 0);
710 osmo_init_logging(&info);
711
712 _log_lines = cmdline_opts.verbose;
713
714 OSMO_ASSERT(osmo_stderr_target);
715 log_set_use_color(osmo_stderr_target, 0);
716 log_set_print_timestamp(osmo_stderr_target, 0);
717 log_set_print_filename(osmo_stderr_target, _log_lines? 1 : 0);
718 log_set_print_category(osmo_stderr_target, 1);
719
720 net = gsm_network_init(tall_bsc_ctx, 1, 1, fake_mncc_recv);
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100721 net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
722 net->gsup_server_port = 0;
723
724 osmo_fsm_log_addr(false);
725 OSMO_ASSERT(msc_vlr_alloc(net) == 0);
726 OSMO_ASSERT(msc_vlr_start(net) == 0);
727 OSMO_ASSERT(net->vlr);
728 OSMO_ASSERT(net->vlr->gsup_client);
729 msc_subscr_conn_init();
730
731 net->vlr->ops.tx_lu_acc = fake_vlr_tx_lu_acc;
732 net->vlr->ops.tx_lu_rej = fake_vlr_tx_lu_rej;
733 net->vlr->ops.tx_cm_serv_acc = fake_vlr_tx_cm_serv_acc;
734 net->vlr->ops.tx_cm_serv_rej = fake_vlr_tx_cm_serv_rej;
735 net->vlr->ops.tx_auth_req = fake_vlr_tx_auth_req;
736 net->vlr->ops.tx_auth_rej = fake_vlr_tx_auth_rej;
737 net->vlr->ops.set_ciph_mode = fake_vlr_tx_ciph_mode_cmd;
738
Neels Hofmeyra1756f32016-05-20 21:59:55 +0200739 clear_vlr();
740
Neels Hofmeyrf8178142017-01-25 15:04:16 +0100741 if (optind >= argc)
742 run_tests(-1);
743 else {
744 int arg;
745 long int nr;
746 for (arg = optind; arg < argc; arg++) {
747 nr = strtol(argv[arg], NULL, 10);
748 if (errno) {
749 fprintf(stderr, "Invalid argument: %s\n",
750 argv[arg]);
751 exit(1);
752 }
753
754 run_tests(nr);
755 }
756 }
757
758 printf("Done\n");
759
760 talloc_free(the_bts);
761
762 check_talloc(msgb_ctx, tall_bsc_ctx, 9);
763 return 0;
764}