blob: 6da34aed6d4b9e91e7ad8e72907e1ecae892fc43 [file] [log] [blame]
Neels Hofmeyr3dc2c642017-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 Hofmeyrd489ea32016-05-20 21:59:55 +020037#include <openbsc/iu.h>
38#include <openbsc/iucs_ranap.h>
Neels Hofmeyr3dc2c642017-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
Neels Hofmeyrde635e72017-03-10 02:15:20 +010072const char *gh_type_name(struct gsm48_hdr *gh)
73{
74 return gsm48_pdisc_msgtype_name(gsm48_hdr_pdisc(gh),
75 gsm48_hdr_msg_type(gh));
76}
77
78const char *msg_type_name(struct msgb *msg)
79{
80 return gh_type_name((void*)msg->data);
81}
82
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +010083void dtap_expect_tx(const char *hex)
84{
Neels Hofmeyrd489ea32016-05-20 21:59:55 +020085 /* Has the previously expected dtap been received? */
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +010086 OSMO_ASSERT(!dtap_tx_expected);
87 if (!hex)
88 return;
89 dtap_tx_expected = msgb_from_hex("dtap_tx_expected", 1024, hex);
90 dtap_tx_confirmed = false;
91}
92
93void dtap_expect_tx_ussd(char *ussd_text)
94{
95 uint8_t ussd_enc[128];
96 int len;
97 /* header */
98 char ussd_msg_hex[128] = "8b2a1c27a225020100302002013b301b04010f0416";
99
100 log("expecting USSD:\n %s", ussd_text);
101 /* append encoded USSD text */
102 gsm_7bit_encode_n_ussd(ussd_enc, sizeof(ussd_enc), ussd_text,
103 &len);
104 strncat(ussd_msg_hex, osmo_hexdump_nospc(ussd_enc, len),
105 sizeof(ussd_msg_hex) - strlen(ussd_msg_hex));
106 dtap_expect_tx(ussd_msg_hex);
107}
108
109int vlr_gsupc_read_cb(struct gsup_client *gsupc, struct msgb *msg);
110
111void gsup_rx(const char *rx_hex, const char *expect_tx_hex)
112{
113 int rc;
114 struct msgb *msg;
115 const char *label;
116
117 gsup_expect_tx(expect_tx_hex);
118
119 msg = msgb_from_hex("gsup", 1024, rx_hex);
120 label = osmo_gsup_message_type_name(msg->l2h[0]);
121 fprintf(stderr, "<-- GSUP rx %s: %s\n", label,
122 osmo_hexdump_nospc(msgb_l2(msg), msgb_l2len(msg)));
123 rc = vlr_gsupc_read_cb(net->vlr->gsup_client, msg);
124 fprintf(stderr, "<-- GSUP rx %s: vlr_gsupc_read_cb() returns %d\n",
125 label, rc);
126 if (expect_tx_hex)
127 OSMO_ASSERT(gsup_tx_confirmed);
128 talloc_free(msg);
129}
130
131bool conn_exists(struct gsm_subscriber_connection *conn)
132{
133 struct gsm_subscriber_connection *c;
134 llist_for_each_entry(c, &net->subscr_conns, entry) {
135 if (c == conn)
136 return true;
137 }
138 return false;
139}
140
141enum ran_type rx_from_ran = RAN_GERAN_A;
142
143struct gsm_subscriber_connection *conn_new(void)
144{
145 struct gsm_subscriber_connection *conn;
146 conn = msc_subscr_con_allocate(net);
147 conn->bts = the_bts;
148 conn->via_ran = rx_from_ran;
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200149 if (conn->via_ran == RAN_UTRAN_IU) {
150 struct ue_conn_ctx *ue_ctx = talloc_zero(conn, struct ue_conn_ctx);
151 *ue_ctx = (struct ue_conn_ctx){
152 .link = (void*)0x23,
153 .conn_id = 42,
154 };
155 conn->iu.ue_ctx = ue_ctx;
156 }
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100157 return conn;
158}
159
160struct gsm_subscriber_connection *g_conn = NULL;
161
162void rx_from_ms(struct msgb *msg)
163{
164 int rc;
165
166 struct gsm48_hdr *gh = msgb_l3(msg);
Neels Hofmeyrde635e72017-03-10 02:15:20 +0100167
168 log("MSC <--%s-- MS: %s",
169 ran_type_name(rx_from_ran),
170 gh_type_name(gh));
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100171
172 if (g_conn && !conn_exists(g_conn))
173 g_conn = NULL;
174
175 if (!g_conn) {
176 log("new conn");
177 g_conn = conn_new();
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200178 rc = msc_compl_l3(g_conn, msg, 23);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100179 if (rc == BSC_API_CONN_POL_REJECT) {
180 msc_subscr_con_free(g_conn);
181 g_conn = NULL;
182 }
183 } else {
184 if ((gsm48_hdr_pdisc(gh) == GSM48_PDISC_RR)
185 && (gsm48_hdr_msg_type(gh) == GSM48_MT_RR_CIPH_M_COMPL))
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200186 msc_cipher_mode_compl(g_conn, msg, 0);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100187 else
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200188 msc_dtap(g_conn, 23, msg);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100189 }
190
191 if (g_conn && !conn_exists(g_conn))
192 g_conn = NULL;
193}
194
195void ms_sends_msg(const char *hex)
196{
197 struct msgb *msg;
198
199 msg = msgb_from_hex("ms_sends_msg", 1024, hex);
200 msg->l1h = msg->l2h = msg->l3h = msg->data;
201 rx_from_ms(msg);
202 talloc_free(msg);
203}
204
205int ms_sends_msg_fake(uint8_t pdisc, uint8_t msg_type)
206{
207 int rc;
208 struct msgb *msg;
209 struct gsm48_hdr *gh;
210
211 msg = msgb_alloc(1024, "ms_sends_msg_fake");
212 msg->l1h = msg->l2h = msg->l3h = msg->data;
213
214 gh = (struct gsm48_hdr*)msgb_put(msg, sizeof(*gh));
215 gh->proto_discr = pdisc;
216 gh->msg_type = msg_type;
217 /* some amount of data, whatever */
218 msgb_put(msg, 123);
219
220 rc = gsm0408_dispatch(g_conn, msg);
221
222 talloc_free(msg);
223 return rc;
224}
225
226void thwart_rx_non_initial_requests()
227{
228 log("requests shall be thwarted");
229 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_CC, GSM48_MT_CC_SETUP) == -EACCES);
230 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_MM, 0x33 /* nonexistent */) == -EACCES);
231 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_RR, GSM48_MT_RR_SYSINFO_1) == -EACCES);
232 OSMO_ASSERT(ms_sends_msg_fake(GSM48_PDISC_SMS, GSM411_MT_CP_DATA) == -EACCES);
233}
234
235void send_sms(struct vlr_subscr *receiver,
236 struct vlr_subscr *sender,
237 char *str)
238{
239 struct gsm_sms *sms = sms_from_text(receiver, sender, 0, str);
240 gsm411_send_sms_subscr(receiver, sms);
241}
242
243unsigned char next_rand_byte = 0;
244/* override, requires '-Wl,--wrap=RAND_bytes' */
245int __real_RAND_bytes(unsigned char *buf, int num);
246int __wrap_RAND_bytes(unsigned char *buf, int num)
247{
248 int i;
249 for (i = 0; i < num; i++)
250 buf[i] = next_rand_byte++;
251 return 1;
252}
253
254/* override, requires '-Wl,--wrap=gsm340_gen_scts' */
255void __real_gsm340_gen_scts(uint8_t *scts, time_t time);
256void __wrap_gsm340_gen_scts(uint8_t *scts, time_t time)
257{
Neels Hofmeyr47b243b2017-08-22 18:06:42 +0200258 /* Write fixed time bytes for deterministic test results */
259 osmo_hexparse("07101000000000", scts, 7);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100260}
261
262const char *paging_expecting_imsi = NULL;
263uint32_t paging_expecting_tmsi;
264bool paging_sent;
265bool paging_stopped;
266
267void paging_expect_imsi(const char *imsi)
268{
269 paging_expecting_imsi = imsi;
270 paging_expecting_tmsi = GSM_RESERVED_TMSI;
271}
272
273void paging_expect_tmsi(uint32_t tmsi)
274{
275 paging_expecting_tmsi = tmsi;
276 paging_expecting_imsi = NULL;
277}
278
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200279int _paging_sent(enum ran_type via_ran, const char *imsi, uint32_t tmsi, uint32_t lac)
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100280{
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200281 log("%s sends out paging request to IMSI %s, TMSI 0x%08x, LAC %u",
282 ran_type_name(via_ran), imsi, tmsi, lac);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100283 OSMO_ASSERT(paging_expecting_imsi || (paging_expecting_tmsi != GSM_RESERVED_TMSI));
284 if (paging_expecting_imsi)
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200285 VERBOSE_ASSERT(strcmp(paging_expecting_imsi, imsi), == 0, "%d");
286 if (paging_expecting_tmsi != GSM_RESERVED_TMSI) {
287 VERBOSE_ASSERT(paging_expecting_tmsi, == tmsi, "0x%08x");
288 }
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100289 paging_sent = true;
290 paging_stopped = false;
291 return 1;
292}
293
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200294/* override, requires '-Wl,--wrap=iu_page_cs' */
295int __real_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac);
296int __wrap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
297{
298 return _paging_sent(RAN_UTRAN_IU, imsi, tmsi ? *tmsi : GSM_RESERVED_TMSI, lac);
299}
300
301/* override, requires '-Wl,--wrap=a_page' */
302int __real_a_page(const char *imsi, uint32_t tmsi, uint16_t lac);
303int __wrap_a_page(const char *imsi, uint32_t tmsi, uint16_t lac)
304{
305 return _paging_sent(RAN_GERAN_A, imsi, tmsi, lac);
306}
307
308/* override, requires '-Wl,--wrap=msc_stop_paging' */
309void __real_msc_stop_paging(struct vlr_subscr *vsub);
310void __wrap_msc_stop_paging(struct vlr_subscr *vsub)
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100311{
312 paging_stopped = true;
313}
314
315void clear_vlr()
316{
317 struct vlr_subscr *vsub, *n;
318 llist_for_each_entry_safe(vsub, n, &net->vlr->subscribers, list) {
319 vlr_subscr_free(vsub);
320 }
321
322 net->authentication_required = false;
323 net->a5_encryption = VLR_CIPH_NONE;
324 net->vlr->cfg.check_imei_rqd = false;
325 net->vlr->cfg.assign_tmsi = false;
Neels Hofmeyr0e255582017-07-18 15:39:27 +0200326 net->vlr->cfg.retrieve_imeisv_early = false;
327 net->vlr->cfg.retrieve_imeisv_ciphered = false;
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100328
329 rx_from_ran = RAN_GERAN_A;
330 auth_request_sent = false;
331 auth_request_expect_rand = NULL;
332 auth_request_expect_autn = NULL;
333
334 next_rand_byte = 0;
335
336 osmo_gettimeofday_override = false;
337}
338
339static struct log_info_cat test_categories[] = {
340 [DMSC] = {
341 .name = "DMSC",
342 .description = "Mobile Switching Center",
343 .enabled = 1, .loglevel = LOGL_DEBUG,
344 },
345 [DRLL] = {
346 .name = "DRLL",
347 .description = "A-bis Radio Link Layer (RLL)",
348 .enabled = 1, .loglevel = LOGL_DEBUG,
349 },
350 [DMM] = {
351 .name = "DMM",
352 .description = "Layer3 Mobility Management (MM)",
353 .enabled = 1, .loglevel = LOGL_DEBUG,
354 },
355 [DRR] = {
356 .name = "DRR",
357 .description = "Layer3 Radio Resource (RR)",
358 .enabled = 1, .loglevel = LOGL_DEBUG,
359 },
360 [DCC] = {
361 .name = "DCC",
362 .description = "Layer3 Call Control (CC)",
363 .enabled = 1, .loglevel = LOGL_NOTICE,
364 },
365 [DMM] = {
366 .name = "DMM",
367 .description = "Layer3 Mobility Management (MM)",
368 .enabled = 1, .loglevel = LOGL_DEBUG,
369 },
370 [DVLR] = {
371 .name = "DVLR",
372 .description = "Visitor Location Register",
373 .enabled = 1, .loglevel = LOGL_DEBUG,
374 },
375 [DREF] = {
376 .name = "DREF",
377 .description = "Reference Counting",
378 .enabled = 1, .loglevel = LOGL_DEBUG,
379 },
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200380 [DPAG] = {
381 .name = "DPAG",
382 .description = "Paging Subsystem",
383 .enabled = 1, .loglevel = LOGL_DEBUG,
384 },
385 [DIUCS] = {
386 .name = "DIUCS",
387 .description = "Iu-CS Protocol",
388 .enabled = 1, .loglevel = LOGL_DEBUG,
389 },
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100390};
391
392static struct log_info info = {
393 .cat = test_categories,
394 .num_cat = ARRAY_SIZE(test_categories),
395};
396
397extern void *tall_bsc_ctx;
398
399int fake_mncc_recv(struct gsm_network *net, struct msgb *msg)
400{
401 fprintf(stderr, "rx MNCC\n");
402 return 0;
403}
404
405/* override, requires '-Wl,--wrap=gsup_client_create' */
406struct gsup_client *
407__real_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
408 gsup_client_read_cb_t read_cb,
409 struct oap_client_config *oap_config);
410struct gsup_client *
411__wrap_gsup_client_create(const char *ip_addr, unsigned int tcp_port,
412 gsup_client_read_cb_t read_cb,
413 struct oap_client_config *oap_config)
414{
415 struct gsup_client *gsupc;
416 gsupc = talloc_zero(tall_bsc_ctx, struct gsup_client);
417 OSMO_ASSERT(gsupc);
418 return gsupc;
419}
420
421/* override, requires '-Wl,--wrap=gsup_client_send' */
422int __real_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
423int __wrap_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
424{
425 const char *is = osmo_hexdump_nospc(msg->data, msg->len);
426 fprintf(stderr, "GSUP --> HLR: %s: %s\n",
427 osmo_gsup_message_type_name(msg->data[0]), is);
428
429 OSMO_ASSERT(gsup_tx_expected);
430 if (strcmp(gsup_tx_expected, is)) {
431 fprintf(stderr, "Mismatch! Expected:\n%s\n", gsup_tx_expected);
432 abort();
433 }
434
435 talloc_free(msg);
436 gsup_tx_confirmed = true;
437 gsup_tx_expected = NULL;
438 return 0;
439}
440
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200441int _validate_dtap(struct msgb *msg, enum ran_type to_ran)
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100442{
Neels Hofmeyrde635e72017-03-10 02:15:20 +0100443 struct gsm48_hdr *gh = (void*)msg->data;
444 btw("DTAP --%s--> MS: %s: %s",
445 ran_type_name(to_ran), msg_type_name(msg),
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200446 osmo_hexdump_nospc(msg->data, msg->len));
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100447
448 OSMO_ASSERT(dtap_tx_expected);
449 if (msg->len != dtap_tx_expected->len
450 || memcmp(msg->data, dtap_tx_expected->data, msg->len)) {
451 fprintf(stderr, "Mismatch! Expected:\n%s\n",
452 osmo_hexdump_nospc(dtap_tx_expected->data,
453 dtap_tx_expected->len));
454 abort();
455 }
456
457 btw("DTAP matches expected message");
458
459 talloc_free(msg);
460 dtap_tx_confirmed = true;
461 talloc_free(dtap_tx_expected);
462 dtap_tx_expected = NULL;
463 return 0;
464}
465
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200466/* override, requires '-Wl,--wrap=iu_tx' */
467int __real_iu_tx(struct msgb *msg, uint8_t sapi);
468int __wrap_iu_tx(struct msgb *msg, uint8_t sapi)
469{
470 return _validate_dtap(msg, RAN_UTRAN_IU);
471}
472
473/* override, requires '-Wl,--wrap=iu_tx_release' */
474int __real_iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause);
475int __wrap_iu_tx_release(struct ue_conn_ctx *ctx, const struct RANAP_Cause *cause)
476{
477 btw("Iu Release --%s--> MS", ran_type_name(RAN_UTRAN_IU));
478 return 0;
479}
480
481/* override, requires '-Wl,--wrap=iu_tx_common_id' */
482int __real_iu_tx_common_id(struct ue_conn_ctx *ue_ctx, const char *imsi);
483int __wrap_iu_tx_common_id(struct ue_conn_ctx *ue_ctx, const char *imsi)
484{
485 btw("Iu Common ID --%s--> MS (IMSI=%s)", ran_type_name(RAN_UTRAN_IU), imsi);
486 return 0;
487}
488
489/* override, requires '-Wl,--wrap=a_tx' */
490int __real_a_tx(struct msgb *msg, uint8_t sapi);
491int __wrap_a_tx(struct msgb *msg, uint8_t sapi)
492{
493 return _validate_dtap(msg, RAN_GERAN_A);
494}
495
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100496static int fake_vlr_tx_lu_acc(void *msc_conn_ref, uint32_t send_tmsi)
497{
498 struct gsm_subscriber_connection *conn = msc_conn_ref;
499 if (send_tmsi == GSM_RESERVED_TMSI)
500 btw("sending LU Accept for %s", vlr_subscr_name(conn->vsub));
501 else
502 btw("sending LU Accept for %s, with TMSI 0x%08x",
503 vlr_subscr_name(conn->vsub), send_tmsi);
504 lu_result_sent |= RES_ACCEPT;
505 return 0;
506}
507
508static int fake_vlr_tx_lu_rej(void *msc_conn_ref, uint8_t cause)
509{
510 struct gsm_subscriber_connection *conn = msc_conn_ref;
511 btw("sending LU Reject for %s, cause %u", vlr_subscr_name(conn->vsub), cause);
512 lu_result_sent |= RES_REJECT;
513 return 0;
514}
515
516static int fake_vlr_tx_cm_serv_acc(void *msc_conn_ref)
517{
518 struct gsm_subscriber_connection *conn = msc_conn_ref;
519 btw("sending CM Service Accept for %s", vlr_subscr_name(conn->vsub));
520 cm_service_result_sent |= RES_ACCEPT;
521 return 0;
522}
523
524static int fake_vlr_tx_cm_serv_rej(void *msc_conn_ref,
525 enum vlr_proc_arq_result result)
526{
527 struct gsm_subscriber_connection *conn = msc_conn_ref;
528 btw("sending CM Service Reject for %s, result %s",
529 vlr_subscr_name(conn->vsub),
530 vlr_proc_arq_result_name(result));
531 cm_service_result_sent |= RES_REJECT;
532 return 0;
533}
534
535static int fake_vlr_tx_auth_req(void *msc_conn_ref, struct gsm_auth_tuple *at,
536 bool send_autn)
537{
538 struct gsm_subscriber_connection *conn = msc_conn_ref;
539 char *hex;
540 bool ok = true;
541 btw("sending %s Auth Request for %s: tuple use_count=%d key_seq=%d auth_types=0x%x and...",
542 send_autn? "UMTS" : "GSM", vlr_subscr_name(conn->vsub),
543 at->use_count, at->key_seq, at->vec.auth_types);
544
545 hex = osmo_hexdump_nospc((void*)&at->vec.rand, sizeof(at->vec.rand));
546 btw("...rand=%s", hex);
547 if (!auth_request_expect_rand
548 || strcmp(hex, auth_request_expect_rand) != 0) {
549 ok = false;
550 log("FAILURE: expected rand=%s",
551 auth_request_expect_rand ? auth_request_expect_rand : "-");
552 }
553
554 if (send_autn) {
555 hex = osmo_hexdump_nospc((void*)&at->vec.autn, sizeof(at->vec.autn));
556 btw("...autn=%s", hex);
557 if (!auth_request_expect_autn
558 || strcmp(hex, auth_request_expect_autn) != 0) {
559 ok = false;
560 log("FAILURE: expected autn=%s",
561 auth_request_expect_autn ? auth_request_expect_autn : "-");
562 }
563 } else if (auth_request_expect_autn) {
564 ok = false;
565 log("FAILURE: no AUTN sent, expected AUTN = %s",
566 auth_request_expect_autn);
567 }
568
569 if (send_autn)
570 btw("...expecting res=%s",
571 osmo_hexdump_nospc((void*)&at->vec.res, at->vec.res_len));
572 else
573 btw("...expecting sres=%s",
574 osmo_hexdump_nospc((void*)&at->vec.sres, sizeof(at->vec.sres)));
575
576 auth_request_sent = ok;
577 return 0;
578}
579
580static int fake_vlr_tx_auth_rej(void *msc_conn_ref)
581{
582 struct gsm_subscriber_connection *conn = msc_conn_ref;
583 btw("sending Auth Reject for %s", vlr_subscr_name(conn->vsub));
584 return 0;
585}
586
587static int fake_vlr_tx_ciph_mode_cmd(void *msc_conn_ref, enum vlr_ciph ciph,
588 bool retrieve_imeisv)
589{
590 /* FIXME: we actually would like to see the message bytes checked here,
591 * not possible while msc_vlr_set_ciph_mode() calls
592 * gsm0808_cipher_mode() directly. When the MSCSPLIT is ready, check
593 * the tx bytes in the sense of dtap_expect_tx() above. */
594 struct gsm_subscriber_connection *conn = msc_conn_ref;
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200595 switch (conn->via_ran) {
596 case RAN_GERAN_A:
597 btw("sending Ciphering Mode Command for %s: cipher=%s kc=%s"
598 " retrieve_imeisv=%d",
599 vlr_subscr_name(conn->vsub),
600 vlr_ciph_name(conn->network->a5_encryption),
601 osmo_hexdump_nospc(conn->vsub->last_tuple->vec.kc, 8),
602 retrieve_imeisv);
603 break;
604 case RAN_UTRAN_IU:
605 btw("sending SecurityModeControl for %s",
606 vlr_subscr_name(conn->vsub));
607 break;
608 default:
609 btw("UNKNOWN RAN TYPE %d", conn->via_ran);
610 OSMO_ASSERT(false);
611 return -1;
612 }
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100613 cipher_mode_cmd_sent = true;
614 cipher_mode_cmd_sent_with_imeisv = retrieve_imeisv;
615 return 0;
616}
617
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200618void ms_sends_security_mode_complete()
619{
620 OSMO_ASSERT(g_conn);
621 OSMO_ASSERT(g_conn->via_ran == RAN_UTRAN_IU);
622 OSMO_ASSERT(g_conn->iu.ue_ctx);
623 msc_rx_sec_mode_compl(g_conn);
624}
625
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100626const struct timeval fake_time_start_time = { 123, 456 };
627
628void fake_time_start()
629{
630 osmo_gettimeofday_override_time = fake_time_start_time;
631 osmo_gettimeofday_override = true;
632 fake_time_passes(0, 0);
633}
634
635void check_talloc(void *msgb_ctx, void *tall_bsc_ctx, int expected_blocks)
636{
637 talloc_report_full(msgb_ctx, stderr);
638 fprintf(stderr, "talloc_total_blocks(tall_bsc_ctx) == %zu\n",
639 talloc_total_blocks(tall_bsc_ctx));
640 if (talloc_total_blocks(tall_bsc_ctx) != expected_blocks)
641 talloc_report_full(tall_bsc_ctx, stderr);
642 fprintf(stderr, "\n");
643}
644
645static struct {
646 bool verbose;
647 int run_test_nr;
648} cmdline_opts = {
649 .verbose = false,
650 .run_test_nr = -1,
651};
652
653static void print_help(const char *program)
654{
655 printf("Usage:\n"
656 " %s [-v] [N [N...]]\n"
657 "Options:\n"
658 " -h --help show this text.\n"
659 " -v --verbose print source file and line numbers\n"
660 " N run only the Nth test (first test is N=1)\n",
661 program
662 );
663}
664
665static void handle_options(int argc, char **argv)
666{
667 while (1) {
668 int option_index = 0, c;
669 static struct option long_options[] = {
670 {"help", 0, 0, 'h'},
671 {"verbose", 1, 0, 'v'},
672 {0, 0, 0, 0}
673 };
674
675 c = getopt_long(argc, argv, "hv",
676 long_options, &option_index);
677 if (c == -1)
678 break;
679
680 switch (c) {
681 case 'h':
682 print_help(argv[0]);
683 exit(0);
684 case 'v':
685 cmdline_opts.verbose = true;
686 break;
687 default:
688 /* catch unknown options *as well as* missing arguments. */
689 fprintf(stderr, "Error in command line options. Exiting.\n");
690 exit(-1);
691 break;
692 }
693 }
694}
695
696void *msgb_ctx = NULL;
697
698void run_tests(int nr)
699{
700 int test_nr;
701 nr --; /* arg's first test is 1, in here it's 0 */
702 for (test_nr = 0; msc_vlr_tests[test_nr]; test_nr ++) {
703 if (nr >= 0 && test_nr != nr)
704 continue;
705
706 if (cmdline_opts.verbose)
707 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
708
709 msc_vlr_tests[test_nr]();
710
711 if (cmdline_opts.verbose)
712 fprintf(stderr, "(test nr %d)\n", test_nr + 1);
713
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200714 check_talloc(msgb_ctx, tall_bsc_ctx, 9);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100715 } while(0);
716}
717
718int main(int argc, char **argv)
719{
720 handle_options(argc, argv);
721
722 tall_bsc_ctx = talloc_named_const(NULL, 0, "subscr_conn_test_ctx");
723 msgb_ctx = msgb_talloc_ctx_init(tall_bsc_ctx, 0);
724 osmo_init_logging(&info);
725
726 _log_lines = cmdline_opts.verbose;
727
728 OSMO_ASSERT(osmo_stderr_target);
729 log_set_use_color(osmo_stderr_target, 0);
730 log_set_print_timestamp(osmo_stderr_target, 0);
731 log_set_print_filename(osmo_stderr_target, _log_lines? 1 : 0);
732 log_set_print_category(osmo_stderr_target, 1);
733
734 net = gsm_network_init(tall_bsc_ctx, 1, 1, fake_mncc_recv);
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100735 net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server");
736 net->gsup_server_port = 0;
737
738 osmo_fsm_log_addr(false);
739 OSMO_ASSERT(msc_vlr_alloc(net) == 0);
740 OSMO_ASSERT(msc_vlr_start(net) == 0);
741 OSMO_ASSERT(net->vlr);
742 OSMO_ASSERT(net->vlr->gsup_client);
743 msc_subscr_conn_init();
744
745 net->vlr->ops.tx_lu_acc = fake_vlr_tx_lu_acc;
746 net->vlr->ops.tx_lu_rej = fake_vlr_tx_lu_rej;
747 net->vlr->ops.tx_cm_serv_acc = fake_vlr_tx_cm_serv_acc;
748 net->vlr->ops.tx_cm_serv_rej = fake_vlr_tx_cm_serv_rej;
749 net->vlr->ops.tx_auth_req = fake_vlr_tx_auth_req;
750 net->vlr->ops.tx_auth_rej = fake_vlr_tx_auth_rej;
751 net->vlr->ops.set_ciph_mode = fake_vlr_tx_ciph_mode_cmd;
752
Neels Hofmeyrd489ea32016-05-20 21:59:55 +0200753 clear_vlr();
754
Neels Hofmeyr3dc2c642017-01-25 15:04:16 +0100755 if (optind >= argc)
756 run_tests(-1);
757 else {
758 int arg;
759 long int nr;
760 for (arg = optind; arg < argc; arg++) {
761 nr = strtol(argv[arg], NULL, 10);
762 if (errno) {
763 fprintf(stderr, "Invalid argument: %s\n",
764 argv[arg]);
765 exit(1);
766 }
767
768 run_tests(nr);
769 }
770 }
771
772 printf("Done\n");
773
774 talloc_free(the_bts);
775
776 check_talloc(msgb_ctx, tall_bsc_ctx, 9);
777 return 0;
778}