blob: 981a557ce7397f5eb171d6ddc1cca71a6d4bc72c [file] [log] [blame]
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001/* Test the SGSN */
2/*
3 * (C) 2014 by Holger Hans Peter Freyther
4 * (C) 2014 by sysmocom s.f.m.c. GmbH
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020022#include <openbsc/gprs_llc.h>
23#include <openbsc/sgsn.h>
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020024#include <openbsc/gprs_gmm.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020025#include <openbsc/debug.h>
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010026#include <openbsc/gsm_subscriber.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020027
Jacob Erlbeck189999d2014-10-27 14:34:13 +010028#include <osmocom/gprs/gprs_bssgp.h>
29
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020030#include <osmocom/gsm/gsm_utils.h>
31
32#include <osmocom/core/application.h>
33#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010034#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020035
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020036#include <stdio.h>
37
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020038extern void *tall_msgb_ctx;
39
40void *tall_bsc_ctx;
41static struct sgsn_instance sgsn_inst = {
42 .config_file = "osmo_sgsn.cfg",
43 .cfg = {
44 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010045 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020046 },
47};
48struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010049unsigned sgsn_tx_counter = 0;
50
51/* override */
52int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
53 struct bssgp_dl_ud_par *dup)
54{
55 sgsn_tx_counter += 1;
56 return 0;
57}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020058
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010059/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
60void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *, struct gsm_subscriber *);
61void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *, struct gsm_subscriber *) =
62 &__real_sgsn_update_subscriber_data;
63
64void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
65 struct gsm_subscriber *subscr)
66{
67 (*update_subscriber_data_cb)(mmctx, subscr);
68}
69
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010070/* override, requires '-Wl,--wrap=gprs_subscr_request_update' */
71int __real_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx);
72int (*subscr_request_update_cb)(struct sgsn_mm_ctx *mmctx) =
73 &__real_gprs_subscr_request_update;
74
75int __wrap_gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
76 return (*subscr_request_update_cb)(mmctx);
77};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010078
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020079static int count(struct llist_head *head)
80{
81 struct llist_head *cur;
82 int count = 0;
83
84 llist_for_each(cur, head)
85 count += 1;
86
87 return count;
88}
89
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020090static struct msgb *create_msg(const uint8_t *data, size_t len)
91{
92 struct msgb *msg = msgb_alloc(len + 8, "test message");
93 msg->l1h = msgb_put(msg, 8);
94 msg->l2h = msgb_put(msg, len);
95 memcpy(msg->l2h, data, len);
96
97 msgb_bcid(msg) = msg->l1h;
98 msgb_gmmh(msg) = msg->l2h;
99 return msg;
100}
101
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100102/*
103 * Create a context and search for it
104 */
105static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
106{
107 struct sgsn_mm_ctx *ctx, *ictx;
108 struct gprs_llc_lle *lle;
109 int old_count = count(gprs_llme_list());
110
111 lle = gprs_lle_get_or_create(tlli, 3);
112 ctx = sgsn_mm_ctx_alloc(tlli, raid);
113 ctx->mm_state = GMM_REGISTERED_NORMAL;
114 ctx->llme = lle->llme;
115
116 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
117 OSMO_ASSERT(ictx == ctx);
118
119 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
120
121 return ctx;
122}
123
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100124static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
125 const uint8_t *data, size_t data_len)
126{
127 struct msgb *msg;
128
129 sgsn_tx_counter = 0;
130
131 msg = create_msg(data, data_len);
132 msgb_tlli(msg) = tlli;
133 gsm0408_gprs_rcvmsg(msg, llme);
134 msgb_free(msg);
135}
136
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200137static void test_llme(void)
138{
139 struct gprs_llc_lle *lle, *lle_copy;
140 uint32_t local_tlli;
141 uint32_t foreign_tlli;
142
143 printf("Testing LLME allocations\n");
144 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
145 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
146
147 /* initial state */
148 OSMO_ASSERT(count(gprs_llme_list()) == 0);
149
150 /* Create a new entry */
151 lle = gprs_lle_get_or_create(local_tlli, 3);
152 OSMO_ASSERT(lle);
153 OSMO_ASSERT(count(gprs_llme_list()) == 1);
154
155 /* No new entry is created */
156 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
157 OSMO_ASSERT(lle == lle_copy);
158 OSMO_ASSERT(count(gprs_llme_list()) == 1);
159 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
160 OSMO_ASSERT(lle == lle_copy);
161 OSMO_ASSERT(count(gprs_llme_list()) == 1);
162
163 /* unassign which should delete it*/
164 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
165
166 /* Check that everything was cleaned up */
167 OSMO_ASSERT(count(gprs_llme_list()) == 0);
168}
169
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100170struct gsm_subscriber *last_updated_subscr = NULL;
171void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
172 struct gsm_subscriber *subscr)
173{
174 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
175 __func__, mmctx, subscr);
176 last_updated_subscr = subscr;
177}
178
179static void test_subscriber(void)
180{
181 struct gsm_subscriber *s1, *s2, *s1found, *s2found;
182 const char *imsi1 = "1234567890";
183 const char *imsi2 = "9876543210";
184
185 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
186
187 printf("Testing core subscriber data API\n");
188
189 /* Check for emptiness */
190 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
191 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
192
193 /* Allocate entry 1 */
194 s1 = gprs_subscr_get_or_create(imsi1);
195 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
196 s1found = gprs_subscr_get_by_imsi(imsi1);
197 OSMO_ASSERT(s1found == s1);
198 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
199 subscr_put(s1found);
200
201 /* Allocate entry 2 */
202 s2 = gprs_subscr_get_or_create(imsi2);
203 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
204 s1found = gprs_subscr_get_by_imsi(imsi1);
205 s2found = gprs_subscr_get_by_imsi(imsi2);
206 OSMO_ASSERT(s1found == s1);
207 OSMO_ASSERT(s2found == s2);
208 subscr_put(s1found);
209 subscr_put(s2found);
210
211 /* Update entry 1 */
212 last_updated_subscr = NULL;
213 gprs_subscr_update(s1);
214 OSMO_ASSERT(last_updated_subscr == s1);
215
216 /* Because of the update, it won't be freed on delete now */
217 gprs_subscr_delete(s1);
218 s1found = gprs_subscr_get_by_imsi(imsi1);
219 OSMO_ASSERT(s1found != NULL);
220 s1 = s1found;
221
222 /* Cancel it, so that delete will free it.
223 * Refcount it to make sure s1 won't be freed here */
224 last_updated_subscr = NULL;
225 gprs_subscr_put_and_cancel(subscr_get(s1));
226 OSMO_ASSERT(last_updated_subscr == s1);
227
228 /* Cancelled entries are still being found */
229 s1found = gprs_subscr_get_by_imsi(imsi1);
230 OSMO_ASSERT(s1found != NULL);
231 subscr_put(s1found);
232
233 /* Free entry 1 */
234 gprs_subscr_delete(s1);
235 s1 = NULL;
236 s2found = gprs_subscr_get_by_imsi(imsi2);
237 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
238 OSMO_ASSERT(s2found == s2);
239 subscr_put(s2found);
240
241 /* Free entry 2 */
242 gprs_subscr_delete(s2);
243 s2 = NULL;
244 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
245 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
246
247 OSMO_ASSERT(llist_empty(&active_subscribers));
248
249 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
250}
251
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200252/*
253 * Test that a GMM Detach will remove the MMCTX and the
254 * associated LLME.
255 */
256static void test_gmm_detach(void)
257{
258 struct gprs_ra_id raid = { 0, };
259 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200260 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200261
262 printf("Testing GMM detach\n");
263
264 /* DTAP - Detach Request (MO) */
265 /* normal detach, power_off = 0 */
266 static const unsigned char detach_req[] = {
267 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
268 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
269 };
270
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200271 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200272
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100273 /* Create a context */
274 OSMO_ASSERT(count(gprs_llme_list()) == 0);
275 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200276
277 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100278 send_0408_message(ctx->llme, local_tlli,
279 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200280
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100281 /* verify that a single message (hopefully the Detach Accept) has been
282 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100283 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100284
285 /* verify that things are gone */
286 OSMO_ASSERT(count(gprs_llme_list()) == 0);
287 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
288 OSMO_ASSERT(!ictx);
289}
290
291/*
292 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
293 * will not sent a Detach Accept message (power_off = 1)
294 */
295static void test_gmm_detach_power_off(void)
296{
297 struct gprs_ra_id raid = { 0, };
298 struct sgsn_mm_ctx *ctx, *ictx;
299 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100300
301 printf("Testing GMM detach (power off)\n");
302
303 /* DTAP - Detach Request (MO) */
304 /* normal detach, power_off = 1 */
305 static const unsigned char detach_req[] = {
306 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
307 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
308 };
309
310 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
311
312 /* Create a context */
313 OSMO_ASSERT(count(gprs_llme_list()) == 0);
314 ctx = alloc_mm_ctx(local_tlli, &raid);
315
316 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100317 send_0408_message(ctx->llme, local_tlli,
318 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100319
320 /* verify that no message (and therefore no Detach Accept) has been
321 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100322 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100323
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200324 /* verify that things are gone */
325 OSMO_ASSERT(count(gprs_llme_list()) == 0);
326 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200327 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200328}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200329
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200330/*
331 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
332 */
333static void test_gmm_detach_no_mmctx(void)
334{
335 struct gprs_llc_lle *lle;
336 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200337
338 printf("Testing GMM detach (no MMCTX)\n");
339
340 /* DTAP - Detach Request (MO) */
341 /* normal detach, power_off = 0 */
342 static const unsigned char detach_req[] = {
343 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
344 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
345 };
346
347 /* Create an LLME */
348 OSMO_ASSERT(count(gprs_llme_list()) == 0);
349 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
350 lle = gprs_lle_get_or_create(local_tlli, 3);
351
352 OSMO_ASSERT(count(gprs_llme_list()) == 1);
353
354 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100355 send_0408_message(lle->llme, local_tlli,
356 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200357
358 /* verify that the LLME is gone */
359 OSMO_ASSERT(count(gprs_llme_list()) == 0);
360}
361
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100362/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100363 * Test that a single GMM Detach Accept message will not cause the SGSN to send
364 * any message or leave an MM context at the SGSN.
365 */
366static void test_gmm_detach_accept_unexpected(void)
367{
368 struct gprs_llc_lle *lle;
369 uint32_t local_tlli;
370
371 printf("Testing GMM detach accept (unexpected)\n");
372
373 /* DTAP - Detach Accept (MT) */
374 /* normal detach */
375 static const unsigned char detach_acc[] = {
376 0x08, 0x06
377 };
378
379 /* Create an LLME */
380 OSMO_ASSERT(count(gprs_llme_list()) == 0);
381 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
382 lle = gprs_lle_get_or_create(local_tlli, 3);
383
384 /* inject the detach */
385 send_0408_message(lle->llme, local_tlli,
386 detach_acc, ARRAY_SIZE(detach_acc));
387
388 /* verify that no message (and therefore no Status or XID reset) has been
389 * sent by the SGSN */
390 OSMO_ASSERT(sgsn_tx_counter == 0);
391
392 /* verify that things are gone */
393 OSMO_ASSERT(count(gprs_llme_list()) == 0);
394}
395
396/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100397 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
398 */
399static void test_gmm_status_no_mmctx(void)
400{
401 struct gprs_llc_lle *lle;
402 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100403
404 printf("Testing GMM Status (no MMCTX)\n");
405
406 /* DTAP - GMM Status, protocol error */
407 static const unsigned char gmm_status[] = {
408 0x08, 0x20, 0x6f
409 };
410
411 /* Create an LLME */
412 OSMO_ASSERT(count(gprs_llme_list()) == 0);
413 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
414 lle = gprs_lle_get_or_create(local_tlli, 3);
415
416 OSMO_ASSERT(count(gprs_llme_list()) == 1);
417
418 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100419 send_0408_message(lle->llme, local_tlli,
420 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100421
422 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100423 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100424
425 /* verify that the LLME is gone */
426 OSMO_ASSERT(count(gprs_llme_list()) == 0);
427}
428
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100429/*
430 * Test the GMM Attach procedure
431 */
432static void test_gmm_attach(void)
433{
434 struct gprs_ra_id raid = { 0, };
435 struct sgsn_mm_ctx *ctx = NULL;
436 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100437 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100438 uint32_t foreign_tlli;
439 uint32_t local_tlli = 0;
440 struct gprs_llc_lle *lle;
441
442 /* DTAP - Attach Request */
443 /* The P-TMSI is not known by the SGSN */
444 static const unsigned char attach_req[] = {
445 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
446 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
447 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
448 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
449 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
450 };
451
452 /* DTAP - Identity Response IMEI */
453 static const unsigned char ident_resp_imei[] = {
454 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
455 0x56
456 };
457
458 /* DTAP - Identity Response IMSI */
459 static const unsigned char ident_resp_imsi[] = {
460 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
461 0x54
462 };
463
464 /* DTAP - Attach Complete */
465 static const unsigned char attach_compl[] = {
466 0x08, 0x03
467 };
468
469 /* DTAP - Detach Request (MO) */
470 /* normal detach, power_off = 0 */
471 static const unsigned char detach_req[] = {
472 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
473 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
474 };
475
476 printf("Testing GMM attach\n");
477
478 /* reset the PRNG used by sgsn_alloc_ptmsi */
479 srand(1);
480
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100481 ptmsi1 = sgsn_alloc_ptmsi();
482 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
483
484 /* reset the PRNG, so that the same P-TMSI sequence will be generated
485 * again */
486 srand(1);
487
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100488 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
489
490 /* Create a LLE/LLME */
491 OSMO_ASSERT(count(gprs_llme_list()) == 0);
492 lle = gprs_lle_get_or_create(foreign_tlli, 3);
493 OSMO_ASSERT(count(gprs_llme_list()) == 1);
494
495 /* inject the attach request */
496 send_0408_message(lle->llme, foreign_tlli,
497 attach_req, ARRAY_SIZE(attach_req));
498
499 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
500 OSMO_ASSERT(ctx != NULL);
501 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
502
503 /* we expect an identity request (IMEI) */
504 OSMO_ASSERT(sgsn_tx_counter == 1);
505
506 /* inject the identity response (IMEI) */
507 send_0408_message(ctx->llme, foreign_tlli,
508 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
509
510 /* we expect an identity request (IMSI) */
511 OSMO_ASSERT(sgsn_tx_counter == 1);
512
513 /* inject the identity response (IMSI) */
514 send_0408_message(ctx->llme, foreign_tlli,
515 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
516
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100517 /* check that the MM context has not been removed due to a failed
518 * authorization */
519 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
520
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100521 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100522
523 /* we expect an attach accept/reject */
524 OSMO_ASSERT(sgsn_tx_counter == 1);
525
526 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100527 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100528
529 /* inject the attach complete */
530 send_0408_message(ctx->llme, local_tlli,
531 attach_compl, ARRAY_SIZE(attach_compl));
532
533 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
534
535 /* we don't expect a response */
536 OSMO_ASSERT(sgsn_tx_counter == 0);
537
538 /* inject the detach */
539 send_0408_message(ctx->llme, local_tlli,
540 detach_req, ARRAY_SIZE(detach_req));
541
542 /* verify that things are gone */
543 OSMO_ASSERT(count(gprs_llme_list()) == 0);
544 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
545 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100546}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100547
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100548static void test_gmm_attach_acl(void)
549{
550 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
551
552 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
553 sgsn_acl_add("123456789012345", &sgsn->cfg);
554 printf("Auth policy 'closed': ");
555 test_gmm_attach();
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100556 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100557
558 sgsn->cfg.auth_policy = saved_auth_policy;
559}
560
561int my_subscr_request_update(struct sgsn_mm_ctx *mmctx) {
562 int rc;
563 rc = __real_gprs_subscr_request_update(mmctx);
564 if (rc == -ENOTSUP) {
565 OSMO_ASSERT(mmctx->subscr);
566 gprs_subscr_update(mmctx->subscr);
567 }
568 return rc;
569};
570
571static void test_gmm_attach_subscr(void)
572{
573 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
574 struct gsm_subscriber *subscr;
575
576 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
577 subscr_request_update_cb = my_subscr_request_update;
578
579 subscr = gprs_subscr_get_or_create("123456789012345");
580 subscr->authorized = 1;
581 subscr_put(subscr);
582
583 printf("Auth policy 'remote': ");
584 test_gmm_attach();
585
586 subscr = gprs_subscr_get_by_imsi("123456789012345");
587 OSMO_ASSERT(subscr != NULL);
588 gprs_subscr_delete(subscr);
589
590 sgsn->cfg.auth_policy = saved_auth_policy;
591 subscr_request_update_cb = __real_gprs_subscr_request_update;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100592}
593
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100594/*
595 * Test the GMM Rejects
596 */
597static void test_gmm_reject(void)
598{
599 struct gprs_ra_id raid = { 0, };
600 struct sgsn_mm_ctx *ctx = NULL;
601 uint32_t foreign_tlli;
602 struct gprs_llc_lle *lle;
603 int idx;
604
605 /* DTAP - Attach Request */
606 /* Invalid MI length */
607 static const unsigned char attach_req_inv_mi_len[] = {
608 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
609 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
610 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
611 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
612 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
613 };
614
615 /* DTAP - Attach Request */
616 /* Invalid MI type (IMEI) */
617 static const unsigned char attach_req_inv_mi_type[] = {
618 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
619 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
620 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
621 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
622 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
623 };
624
625 /* DTAP - Routing Area Update Request */
626 static const unsigned char dtap_ra_upd_req[] = {
627 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
628 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
629 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
630 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
631 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
632 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
633 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
634 };
635
636 /* DTAP - Routing Area Update Request */
637 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
638 static const unsigned char dtap_ra_upd_req_inv_type[] = {
639 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
640 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
641 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
642 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
643 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
644 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
645 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
646 };
647
648 /* DTAP - Routing Area Update Request */
649 /* Invalid cap length */
650 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
651 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
652 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
653 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
654 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
655 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
656 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
657 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
658 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
659 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
660 };
661
662 struct test {
663 const char *title;
664 const unsigned char *msg;
665 unsigned msg_len;
666 unsigned num_resp;
667
668 };
669 static struct test tests[] = {
670 {
671 .title = "Attach Request (invalid MI length)",
672 .msg = attach_req_inv_mi_len,
673 .msg_len = sizeof(attach_req_inv_mi_len),
674 .num_resp = 1 /* Reject */
675
676 },
677 {
678 .title = "Attach Request (invalid MI type)",
679 .msg = attach_req_inv_mi_type,
680 .msg_len = sizeof(attach_req_inv_mi_type),
681 .num_resp = 1 /* Reject */
682 },
683 {
684 .title = "Routing Area Update Request (valid)",
685 .msg = dtap_ra_upd_req,
686 .msg_len = sizeof(dtap_ra_upd_req),
687 .num_resp = 2 /* XID Reset + Reject */
688 },
689 {
690 .title = "Routing Area Update Request (invalid type)",
691 .msg = dtap_ra_upd_req_inv_type,
692 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
693 .num_resp = 1 /* Reject */
694 },
695 {
696 .title = "Routing Area Update Request (invalid CAP length)",
697 .msg = dtap_ra_upd_req_inv_cap_len,
698 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
699 .num_resp = 1 /* Reject */
700 },
701 };
702
703 printf("Testing GMM reject\n");
704
705 /* reset the PRNG used by sgsn_alloc_ptmsi */
706 srand(1);
707
708 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
709
710 OSMO_ASSERT(count(gprs_llme_list()) == 0);
711
712 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
713 const struct test *test = &tests[idx];
714 printf(" - %s\n", test->title);
715
716 /* Create a LLE/LLME */
717 lle = gprs_lle_get_or_create(foreign_tlli, 3);
718 OSMO_ASSERT(count(gprs_llme_list()) == 1);
719
720 /* Inject the Request message */
721 send_0408_message(lle->llme, foreign_tlli,
722 test->msg, test->msg_len);
723
724 /* We expect a Reject message */
725 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
726 sgsn_tx_counter, test->num_resp);
727 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
728
729 /* verify that LLME/MM are removed */
730 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
731 OSMO_ASSERT(ctx == NULL);
732 OSMO_ASSERT(count(gprs_llme_list()) == 0);
733 }
734}
735
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100736/*
737 * Test the dynamic allocation of P-TMSIs
738 */
739static void test_gmm_ptmsi_allocation(void)
740{
741 struct gprs_ra_id raid = { 0, };
742 struct sgsn_mm_ctx *ctx = NULL;
743 struct sgsn_mm_ctx *ictx;
744 uint32_t foreign_tlli;
745 uint32_t ptmsi1;
746 uint32_t ptmsi2;
747 uint32_t old_ptmsi;
748 uint32_t local_tlli = 0;
749 struct gprs_llc_lle *lle;
750 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
751
752 /* DTAP - Attach Request (IMSI 12131415161718) */
753 static const unsigned char attach_req[] = {
754 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
755 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
756 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
757 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
758 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
759 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
760 0x00,
761 };
762
763 /* DTAP - Identity Response IMEI */
764 static const unsigned char ident_resp_imei[] = {
765 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
766 0x56
767 };
768
769 /* DTAP - Attach Complete */
770 static const unsigned char attach_compl[] = {
771 0x08, 0x03
772 };
773
774 /* DTAP - Routing Area Update Request */
775 static const unsigned char ra_upd_req[] = {
776 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
777 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
778 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
779 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
780 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
781 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
782 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
783 };
784
785 /* DTAP - Routing Area Update Complete */
786 static const unsigned char ra_upd_complete[] = {
787 0x08, 0x0a
788 };
789
790 /* DTAP - Detach Request (MO) */
791 /* normal detach, power_off = 1 */
792 static const unsigned char detach_req[] = {
793 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
794 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
795 };
796
797 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
798
799 printf("Testing P-TMSI allocation\n");
800
801 printf(" - sgsn_alloc_ptmsi\n");
802
803 /* reset the PRNG used by sgsn_alloc_ptmsi */
804 srand(1);
805
806 ptmsi1 = sgsn_alloc_ptmsi();
807 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
808
809 ptmsi2 = sgsn_alloc_ptmsi();
810 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
811
812 OSMO_ASSERT(ptmsi1 != ptmsi2);
813
814 printf(" - Repeated Attach Request\n");
815
816 /* reset the PRNG, so that the same P-TMSI will be generated
817 * again */
818 srand(1);
819
820 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
821
822 /* Create a LLE/LLME */
823 OSMO_ASSERT(count(gprs_llme_list()) == 0);
824 lle = gprs_lle_get_or_create(foreign_tlli, 3);
825 OSMO_ASSERT(count(gprs_llme_list()) == 1);
826
827 /* inject the attach request */
828 send_0408_message(lle->llme, foreign_tlli,
829 attach_req, ARRAY_SIZE(attach_req));
830
831 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
832 OSMO_ASSERT(ctx != NULL);
833 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
834 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
835
836 old_ptmsi = ctx->p_tmsi_old;
837
838 /* we expect an identity request (IMEI) */
839 OSMO_ASSERT(sgsn_tx_counter == 1);
840
841 /* inject the identity response (IMEI) */
842 send_0408_message(ctx->llme, foreign_tlli,
843 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
844
845 /* check that the MM context has not been removed due to a failed
846 * authorization */
847 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
848
849 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
850 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
851
852 /* we expect an attach accept */
853 OSMO_ASSERT(sgsn_tx_counter == 1);
854
855 /* we ignore this and send the attach again */
856 send_0408_message(lle->llme, foreign_tlli,
857 attach_req, ARRAY_SIZE(attach_req));
858
859 /* the allocated P-TMSI should be the same */
860 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
861 OSMO_ASSERT(ctx != NULL);
862 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
863 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
864 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
865
866 /* inject the attach complete */
867 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
868 send_0408_message(ctx->llme, local_tlli,
869 attach_compl, ARRAY_SIZE(attach_compl));
870
871 /* we don't expect a response */
872 OSMO_ASSERT(sgsn_tx_counter == 0);
873
874 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
875 OSMO_ASSERT(ctx->p_tmsi_old == 0);
876 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
877
878 printf(" - Repeated RA Update Request\n");
879
880 /* inject the RA update request */
881 send_0408_message(ctx->llme, local_tlli,
882 ra_upd_req, ARRAY_SIZE(ra_upd_req));
883
884 /* we expect an RA update accept */
885 OSMO_ASSERT(sgsn_tx_counter == 1);
886
887 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
888 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
889 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
890
891 /* repeat the RA update request */
892 send_0408_message(ctx->llme, local_tlli,
893 ra_upd_req, ARRAY_SIZE(ra_upd_req));
894
895 /* we expect an RA update accept */
896 OSMO_ASSERT(sgsn_tx_counter == 1);
897
898 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
899 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
900 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
901
902 /* inject the RA update complete */
903 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
904 send_0408_message(ctx->llme, local_tlli,
905 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
906
907 /* we don't expect a response */
908 OSMO_ASSERT(sgsn_tx_counter == 0);
909
910 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
911 OSMO_ASSERT(ctx->p_tmsi_old == 0);
912 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
913
914 /* inject the detach */
915 send_0408_message(ctx->llme, local_tlli,
916 detach_req, ARRAY_SIZE(detach_req));
917
918 /* verify that things are gone */
919 OSMO_ASSERT(count(gprs_llme_list()) == 0);
920 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
921 OSMO_ASSERT(!ictx);
922
923 sgsn->cfg.auth_policy = saved_auth_policy;
924}
925
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200926static struct log_info_cat gprs_categories[] = {
927 [DMM] = {
928 .name = "DMM",
929 .description = "Layer3 Mobility Management (MM)",
930 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100931 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200932 },
933 [DPAG] = {
934 .name = "DPAG",
935 .description = "Paging Subsystem",
936 .color = "\033[1;38m",
937 .enabled = 1, .loglevel = LOGL_NOTICE,
938 },
939 [DMEAS] = {
940 .name = "DMEAS",
941 .description = "Radio Measurement Processing",
942 .enabled = 0, .loglevel = LOGL_NOTICE,
943 },
944 [DREF] = {
945 .name = "DREF",
946 .description = "Reference Counting",
947 .enabled = 0, .loglevel = LOGL_NOTICE,
948 },
949 [DGPRS] = {
950 .name = "DGPRS",
951 .description = "GPRS Packet Service",
952 .enabled = 1, .loglevel = LOGL_DEBUG,
953 },
954 [DNS] = {
955 .name = "DNS",
956 .description = "GPRS Network Service (NS)",
957 .enabled = 1, .loglevel = LOGL_INFO,
958 },
959 [DBSSGP] = {
960 .name = "DBSSGP",
961 .description = "GPRS BSS Gateway Protocol (BSSGP)",
962 .enabled = 1, .loglevel = LOGL_DEBUG,
963 },
964 [DLLC] = {
965 .name = "DLLC",
966 .description = "GPRS Logical Link Control Protocol (LLC)",
967 .enabled = 1, .loglevel = LOGL_DEBUG,
968 },
969 [DSNDCP] = {
970 .name = "DSNDCP",
971 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
972 .enabled = 1, .loglevel = LOGL_DEBUG,
973 },
974};
975
976static struct log_info info = {
977 .cat = gprs_categories,
978 .num_cat = ARRAY_SIZE(gprs_categories),
979};
980
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200981int main(int argc, char **argv)
982{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200983 osmo_init_logging(&info);
984 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
985 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
986
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +0100987 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100988 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100989
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200990 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100991 test_subscriber();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200992 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100993 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200994 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100995 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100996 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100997 test_gmm_attach_acl();
998 test_gmm_attach_subscr();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100999 test_gmm_reject();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001000 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001001 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001002 return 0;
1003}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001004
1005
1006/* stubs */
1007struct osmo_prim_hdr;
1008int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1009{
1010 abort();
1011}