blob: c7eec7bdeeb8e9eff501148958b20ef45092921b [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 Erlbeck98a95ac2014-11-28 14:55:25 +010070/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
71int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
72int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
73 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010074
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010075int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
76 return (*subscr_request_update_location_cb)(mmctx);
77};
78
79/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
80int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
81int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
82 &__real_gprs_subscr_request_auth_info;
83
84int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
85 return (*subscr_request_auth_info_cb)(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010086};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010087
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020088static int count(struct llist_head *head)
89{
90 struct llist_head *cur;
91 int count = 0;
92
93 llist_for_each(cur, head)
94 count += 1;
95
96 return count;
97}
98
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020099static struct msgb *create_msg(const uint8_t *data, size_t len)
100{
101 struct msgb *msg = msgb_alloc(len + 8, "test message");
102 msg->l1h = msgb_put(msg, 8);
103 msg->l2h = msgb_put(msg, len);
104 memcpy(msg->l2h, data, len);
105
106 msgb_bcid(msg) = msg->l1h;
107 msgb_gmmh(msg) = msg->l2h;
108 return msg;
109}
110
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100111/*
112 * Create a context and search for it
113 */
114static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
115{
116 struct sgsn_mm_ctx *ctx, *ictx;
117 struct gprs_llc_lle *lle;
118 int old_count = count(gprs_llme_list());
119
120 lle = gprs_lle_get_or_create(tlli, 3);
121 ctx = sgsn_mm_ctx_alloc(tlli, raid);
122 ctx->mm_state = GMM_REGISTERED_NORMAL;
123 ctx->llme = lle->llme;
124
125 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
126 OSMO_ASSERT(ictx == ctx);
127
128 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
129
130 return ctx;
131}
132
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100133static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
134 const uint8_t *data, size_t data_len)
135{
136 struct msgb *msg;
137
138 sgsn_tx_counter = 0;
139
140 msg = create_msg(data, data_len);
141 msgb_tlli(msg) = tlli;
142 gsm0408_gprs_rcvmsg(msg, llme);
143 msgb_free(msg);
144}
145
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200146static void test_llme(void)
147{
148 struct gprs_llc_lle *lle, *lle_copy;
149 uint32_t local_tlli;
150 uint32_t foreign_tlli;
151
152 printf("Testing LLME allocations\n");
153 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
154 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
155
156 /* initial state */
157 OSMO_ASSERT(count(gprs_llme_list()) == 0);
158
159 /* Create a new entry */
160 lle = gprs_lle_get_or_create(local_tlli, 3);
161 OSMO_ASSERT(lle);
162 OSMO_ASSERT(count(gprs_llme_list()) == 1);
163
164 /* No new entry is created */
165 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
166 OSMO_ASSERT(lle == lle_copy);
167 OSMO_ASSERT(count(gprs_llme_list()) == 1);
168 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
169 OSMO_ASSERT(lle == lle_copy);
170 OSMO_ASSERT(count(gprs_llme_list()) == 1);
171
172 /* unassign which should delete it*/
173 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
174
175 /* Check that everything was cleaned up */
176 OSMO_ASSERT(count(gprs_llme_list()) == 0);
177}
178
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100179struct gsm_subscriber *last_updated_subscr = NULL;
180void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
181 struct gsm_subscriber *subscr)
182{
183 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
184 __func__, mmctx, subscr);
185 last_updated_subscr = subscr;
186}
187
188static void test_subscriber(void)
189{
190 struct gsm_subscriber *s1, *s2, *s1found, *s2found;
191 const char *imsi1 = "1234567890";
192 const char *imsi2 = "9876543210";
193
194 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
195
196 printf("Testing core subscriber data API\n");
197
198 /* Check for emptiness */
199 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
200 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
201
202 /* Allocate entry 1 */
203 s1 = gprs_subscr_get_or_create(imsi1);
204 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
205 s1found = gprs_subscr_get_by_imsi(imsi1);
206 OSMO_ASSERT(s1found == s1);
207 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
208 subscr_put(s1found);
209
210 /* Allocate entry 2 */
211 s2 = gprs_subscr_get_or_create(imsi2);
212 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
213 s1found = gprs_subscr_get_by_imsi(imsi1);
214 s2found = gprs_subscr_get_by_imsi(imsi2);
215 OSMO_ASSERT(s1found == s1);
216 OSMO_ASSERT(s2found == s2);
217 subscr_put(s1found);
218 subscr_put(s2found);
219
220 /* Update entry 1 */
221 last_updated_subscr = NULL;
222 gprs_subscr_update(s1);
223 OSMO_ASSERT(last_updated_subscr == s1);
224
225 /* Because of the update, it won't be freed on delete now */
226 gprs_subscr_delete(s1);
227 s1found = gprs_subscr_get_by_imsi(imsi1);
228 OSMO_ASSERT(s1found != NULL);
229 s1 = s1found;
230
231 /* Cancel it, so that delete will free it.
232 * Refcount it to make sure s1 won't be freed here */
233 last_updated_subscr = NULL;
234 gprs_subscr_put_and_cancel(subscr_get(s1));
235 OSMO_ASSERT(last_updated_subscr == s1);
236
237 /* Cancelled entries are still being found */
238 s1found = gprs_subscr_get_by_imsi(imsi1);
239 OSMO_ASSERT(s1found != NULL);
240 subscr_put(s1found);
241
242 /* Free entry 1 */
243 gprs_subscr_delete(s1);
244 s1 = NULL;
245 s2found = gprs_subscr_get_by_imsi(imsi2);
246 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
247 OSMO_ASSERT(s2found == s2);
248 subscr_put(s2found);
249
250 /* Free entry 2 */
251 gprs_subscr_delete(s2);
252 s2 = NULL;
253 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
254 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
255
256 OSMO_ASSERT(llist_empty(&active_subscribers));
257
258 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
259}
260
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100261static void test_auth_triplets(void)
262{
263 struct gsm_subscriber *s1, *s1found;
264 const char *imsi1 = "1234567890";
265 struct gsm_auth_tuple *at;
266 struct sgsn_mm_ctx *ctx;
267 struct gprs_ra_id raid = { 0, };
268 uint32_t local_tlli = 0xffeeddcc;
269 struct gprs_llc_llme *llme;
270
271 printf("Testing authentication triplet handling\n");
272
273 /* Check for emptiness */
274 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
275
276 /* Allocate entry 1 */
277 s1 = gprs_subscr_get_or_create(imsi1);
278 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
279 s1found = gprs_subscr_get_by_imsi(imsi1);
280 OSMO_ASSERT(s1found == s1);
281 subscr_put(s1found);
282
283 /* Create a context */
284 OSMO_ASSERT(count(gprs_llme_list()) == 0);
285 ctx = alloc_mm_ctx(local_tlli, &raid);
286
287 /* Attach s1 to ctx */
288 ctx->subscr = subscr_get(s1);
289 ctx->subscr->sgsn_data->mm = ctx;
290
291 /* Try to get auth tuple */
292 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
293 OSMO_ASSERT(at == NULL);
294
295 /* Add triplets */
296 s1->sgsn_data->auth_triplets[0].key_seq = 0;
297 s1->sgsn_data->auth_triplets[1].key_seq = 1;
298 s1->sgsn_data->auth_triplets[2].key_seq = 2;
299
300 /* Try to get auth tuple */
301 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
302 OSMO_ASSERT(at != NULL);
303 OSMO_ASSERT(at->key_seq == 0);
304 OSMO_ASSERT(at->use_count == 1);
305 at = sgsn_auth_get_tuple(ctx, at->key_seq);
306 OSMO_ASSERT(at != NULL);
307 OSMO_ASSERT(at->key_seq == 1);
308 OSMO_ASSERT(at->use_count == 1);
309 at = sgsn_auth_get_tuple(ctx, at->key_seq);
310 OSMO_ASSERT(at != NULL);
311 OSMO_ASSERT(at->key_seq == 2);
312 OSMO_ASSERT(at->use_count == 1);
313 at = sgsn_auth_get_tuple(ctx, at->key_seq);
314 OSMO_ASSERT(at == NULL);
315
316 /* Free MM context and subscriber */
317 subscr_put(s1);
318 llme = ctx->llme;
319 sgsn_mm_ctx_free(ctx);
320 s1found = gprs_subscr_get_by_imsi(imsi1);
321 OSMO_ASSERT(s1found == NULL);
322 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
323}
324
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200325/*
326 * Test that a GMM Detach will remove the MMCTX and the
327 * associated LLME.
328 */
329static void test_gmm_detach(void)
330{
331 struct gprs_ra_id raid = { 0, };
332 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200333 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200334
335 printf("Testing GMM detach\n");
336
337 /* DTAP - Detach Request (MO) */
338 /* normal detach, power_off = 0 */
339 static const unsigned char detach_req[] = {
340 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
341 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
342 };
343
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200344 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200345
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100346 /* Create a context */
347 OSMO_ASSERT(count(gprs_llme_list()) == 0);
348 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200349
350 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100351 send_0408_message(ctx->llme, local_tlli,
352 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200353
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100354 /* verify that a single message (hopefully the Detach Accept) has been
355 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100356 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100357
358 /* verify that things are gone */
359 OSMO_ASSERT(count(gprs_llme_list()) == 0);
360 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
361 OSMO_ASSERT(!ictx);
362}
363
364/*
365 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
366 * will not sent a Detach Accept message (power_off = 1)
367 */
368static void test_gmm_detach_power_off(void)
369{
370 struct gprs_ra_id raid = { 0, };
371 struct sgsn_mm_ctx *ctx, *ictx;
372 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100373
374 printf("Testing GMM detach (power off)\n");
375
376 /* DTAP - Detach Request (MO) */
377 /* normal detach, power_off = 1 */
378 static const unsigned char detach_req[] = {
379 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
380 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
381 };
382
383 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
384
385 /* Create a context */
386 OSMO_ASSERT(count(gprs_llme_list()) == 0);
387 ctx = alloc_mm_ctx(local_tlli, &raid);
388
389 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100390 send_0408_message(ctx->llme, local_tlli,
391 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100392
393 /* verify that no message (and therefore no Detach Accept) has been
394 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100395 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100396
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200397 /* verify that things are gone */
398 OSMO_ASSERT(count(gprs_llme_list()) == 0);
399 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200400 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200401}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200402
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200403/*
404 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
405 */
406static void test_gmm_detach_no_mmctx(void)
407{
408 struct gprs_llc_lle *lle;
409 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200410
411 printf("Testing GMM detach (no MMCTX)\n");
412
413 /* DTAP - Detach Request (MO) */
414 /* normal detach, power_off = 0 */
415 static const unsigned char detach_req[] = {
416 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
417 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
418 };
419
420 /* Create an LLME */
421 OSMO_ASSERT(count(gprs_llme_list()) == 0);
422 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
423 lle = gprs_lle_get_or_create(local_tlli, 3);
424
425 OSMO_ASSERT(count(gprs_llme_list()) == 1);
426
427 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100428 send_0408_message(lle->llme, local_tlli,
429 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200430
431 /* verify that the LLME is gone */
432 OSMO_ASSERT(count(gprs_llme_list()) == 0);
433}
434
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100435/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100436 * Test that a single GMM Detach Accept message will not cause the SGSN to send
437 * any message or leave an MM context at the SGSN.
438 */
439static void test_gmm_detach_accept_unexpected(void)
440{
441 struct gprs_llc_lle *lle;
442 uint32_t local_tlli;
443
444 printf("Testing GMM detach accept (unexpected)\n");
445
446 /* DTAP - Detach Accept (MT) */
447 /* normal detach */
448 static const unsigned char detach_acc[] = {
449 0x08, 0x06
450 };
451
452 /* Create an LLME */
453 OSMO_ASSERT(count(gprs_llme_list()) == 0);
454 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
455 lle = gprs_lle_get_or_create(local_tlli, 3);
456
457 /* inject the detach */
458 send_0408_message(lle->llme, local_tlli,
459 detach_acc, ARRAY_SIZE(detach_acc));
460
461 /* verify that no message (and therefore no Status or XID reset) has been
462 * sent by the SGSN */
463 OSMO_ASSERT(sgsn_tx_counter == 0);
464
465 /* verify that things are gone */
466 OSMO_ASSERT(count(gprs_llme_list()) == 0);
467}
468
469/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100470 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
471 */
472static void test_gmm_status_no_mmctx(void)
473{
474 struct gprs_llc_lle *lle;
475 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100476
477 printf("Testing GMM Status (no MMCTX)\n");
478
479 /* DTAP - GMM Status, protocol error */
480 static const unsigned char gmm_status[] = {
481 0x08, 0x20, 0x6f
482 };
483
484 /* Create an LLME */
485 OSMO_ASSERT(count(gprs_llme_list()) == 0);
486 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
487 lle = gprs_lle_get_or_create(local_tlli, 3);
488
489 OSMO_ASSERT(count(gprs_llme_list()) == 1);
490
491 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100492 send_0408_message(lle->llme, local_tlli,
493 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100494
495 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100496 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100497
498 /* verify that the LLME is gone */
499 OSMO_ASSERT(count(gprs_llme_list()) == 0);
500}
501
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100502/*
503 * Test the GMM Attach procedure
504 */
505static void test_gmm_attach(void)
506{
507 struct gprs_ra_id raid = { 0, };
508 struct sgsn_mm_ctx *ctx = NULL;
509 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100510 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100511 uint32_t foreign_tlli;
512 uint32_t local_tlli = 0;
513 struct gprs_llc_lle *lle;
514
515 /* DTAP - Attach Request */
516 /* The P-TMSI is not known by the SGSN */
517 static const unsigned char attach_req[] = {
518 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
519 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
520 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
521 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
522 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
523 };
524
525 /* DTAP - Identity Response IMEI */
526 static const unsigned char ident_resp_imei[] = {
527 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
528 0x56
529 };
530
531 /* DTAP - Identity Response IMSI */
532 static const unsigned char ident_resp_imsi[] = {
533 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
534 0x54
535 };
536
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100537 /* DTAP - Authentication and Ciphering Resp */
538 static const unsigned char auth_ciph_resp[] = {
539 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
540 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
541 };
542
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100543 /* DTAP - Attach Complete */
544 static const unsigned char attach_compl[] = {
545 0x08, 0x03
546 };
547
548 /* DTAP - Detach Request (MO) */
549 /* normal detach, power_off = 0 */
550 static const unsigned char detach_req[] = {
551 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
552 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
553 };
554
555 printf("Testing GMM attach\n");
556
557 /* reset the PRNG used by sgsn_alloc_ptmsi */
558 srand(1);
559
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100560 ptmsi1 = sgsn_alloc_ptmsi();
561 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
562
563 /* reset the PRNG, so that the same P-TMSI sequence will be generated
564 * again */
565 srand(1);
566
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100567 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
568
569 /* Create a LLE/LLME */
570 OSMO_ASSERT(count(gprs_llme_list()) == 0);
571 lle = gprs_lle_get_or_create(foreign_tlli, 3);
572 OSMO_ASSERT(count(gprs_llme_list()) == 1);
573
574 /* inject the attach request */
575 send_0408_message(lle->llme, foreign_tlli,
576 attach_req, ARRAY_SIZE(attach_req));
577
578 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
579 OSMO_ASSERT(ctx != NULL);
580 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
581
582 /* we expect an identity request (IMEI) */
583 OSMO_ASSERT(sgsn_tx_counter == 1);
584
585 /* inject the identity response (IMEI) */
586 send_0408_message(ctx->llme, foreign_tlli,
587 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
588
589 /* we expect an identity request (IMSI) */
590 OSMO_ASSERT(sgsn_tx_counter == 1);
591
592 /* inject the identity response (IMSI) */
593 send_0408_message(ctx->llme, foreign_tlli,
594 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
595
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100596 /* check that the MM context has not been removed due to a failed
597 * authorization */
598 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
599
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100600 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100601
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100602 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE) {
603 /* we expect an auth & ciph request */
604 OSMO_ASSERT(sgsn_tx_counter == 1);
605
606 /* inject the auth & ciph response */
607 send_0408_message(ctx->llme, foreign_tlli,
608 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
609
610 /* check that the MM context has not been removed due to a
611 * failed authorization */
612 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
613 }
614
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100615 /* we expect an attach accept/reject */
616 OSMO_ASSERT(sgsn_tx_counter == 1);
617
618 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100619 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100620
621 /* inject the attach complete */
622 send_0408_message(ctx->llme, local_tlli,
623 attach_compl, ARRAY_SIZE(attach_compl));
624
625 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
626
627 /* we don't expect a response */
628 OSMO_ASSERT(sgsn_tx_counter == 0);
629
630 /* inject the detach */
631 send_0408_message(ctx->llme, local_tlli,
632 detach_req, ARRAY_SIZE(detach_req));
633
634 /* verify that things are gone */
635 OSMO_ASSERT(count(gprs_llme_list()) == 0);
636 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
637 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100638}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100639
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100640static void test_gmm_attach_acl(void)
641{
642 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
643
644 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
645 sgsn_acl_add("123456789012345", &sgsn->cfg);
646 printf("Auth policy 'closed': ");
647 test_gmm_attach();
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100648 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100649
650 sgsn->cfg.auth_policy = saved_auth_policy;
651}
652
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100653int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100654 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100655 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100656 if (rc == -ENOTSUP) {
657 OSMO_ASSERT(mmctx->subscr);
658 gprs_subscr_update(mmctx->subscr);
659 }
660 return rc;
661};
662
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100663int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
664 gprs_subscr_update(mmctx->subscr);
665 return 0;
666};
667
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100668static void test_gmm_attach_subscr(void)
669{
670 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
671 struct gsm_subscriber *subscr;
672
673 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100674 subscr_request_update_location_cb = my_subscr_request_update_location;
675 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100676
677 subscr = gprs_subscr_get_or_create("123456789012345");
678 subscr->authorized = 1;
679 subscr_put(subscr);
680
681 printf("Auth policy 'remote': ");
682 test_gmm_attach();
683
684 subscr = gprs_subscr_get_by_imsi("123456789012345");
685 OSMO_ASSERT(subscr != NULL);
686 gprs_subscr_delete(subscr);
687
688 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100689 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
690 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100691}
692
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100693int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
694{
695 /* Fake an authentication */
696 OSMO_ASSERT(mmctx->subscr);
697 mmctx->is_authenticated = 1;
698 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100699
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100700 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100701};
702
703static void test_gmm_attach_subscr_fake_auth(void)
704{
705 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
706 struct gsm_subscriber *subscr;
707
708 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100709 subscr_request_update_location_cb = my_subscr_request_update_location;
710 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100711
712 subscr = gprs_subscr_get_or_create("123456789012345");
713 subscr->authorized = 1;
714 subscr->sgsn_data->authenticate = 1;
715 subscr_put(subscr);
716
717 printf("Auth policy 'remote', auth faked: ");
718 test_gmm_attach();
719
720 subscr = gprs_subscr_get_by_imsi("123456789012345");
721 OSMO_ASSERT(subscr != NULL);
722 gprs_subscr_delete(subscr);
723
724 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100725 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
726 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
727}
728
729int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
730{
731 struct gsm_auth_tuple at = {
732 .sres = {0x51, 0xe5, 0x51, 0xe5},
733 .key_seq = 0
734 };
735
736 /* Fake an authentication */
737 OSMO_ASSERT(mmctx->subscr);
738 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
739
740 gprs_subscr_update_auth_info(mmctx->subscr);
741
742 return 0;
743};
744
745static void test_gmm_attach_subscr_real_auth(void)
746{
747 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
748 struct gsm_subscriber *subscr;
749
750 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
751 subscr_request_update_location_cb = my_subscr_request_update_location;
752 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
753
754 subscr = gprs_subscr_get_or_create("123456789012345");
755 subscr->authorized = 1;
756 subscr->sgsn_data->authenticate = 1;
757 subscr_put(subscr);
758
759 printf("Auth policy 'remote', triplet based auth: ");
760 test_gmm_attach();
761
762 subscr = gprs_subscr_get_by_imsi("123456789012345");
763 OSMO_ASSERT(subscr != NULL);
764 gprs_subscr_delete(subscr);
765
766 sgsn->cfg.auth_policy = saved_auth_policy;
767 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
768 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100769}
770
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100771/*
772 * Test the GMM Rejects
773 */
774static void test_gmm_reject(void)
775{
776 struct gprs_ra_id raid = { 0, };
777 struct sgsn_mm_ctx *ctx = NULL;
778 uint32_t foreign_tlli;
779 struct gprs_llc_lle *lle;
780 int idx;
781
782 /* DTAP - Attach Request */
783 /* Invalid MI length */
784 static const unsigned char attach_req_inv_mi_len[] = {
785 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
786 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
787 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
788 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
789 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
790 };
791
792 /* DTAP - Attach Request */
793 /* Invalid MI type (IMEI) */
794 static const unsigned char attach_req_inv_mi_type[] = {
795 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
796 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
797 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
798 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
799 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
800 };
801
802 /* DTAP - Routing Area Update Request */
803 static const unsigned char dtap_ra_upd_req[] = {
804 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
805 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
806 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
807 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
808 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
809 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
810 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
811 };
812
813 /* DTAP - Routing Area Update Request */
814 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
815 static const unsigned char dtap_ra_upd_req_inv_type[] = {
816 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
817 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
818 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
819 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
820 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
821 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
822 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
823 };
824
825 /* DTAP - Routing Area Update Request */
826 /* Invalid cap length */
827 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
828 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
829 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
830 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
831 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
832 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
833 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
834 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
835 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
836 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
837 };
838
839 struct test {
840 const char *title;
841 const unsigned char *msg;
842 unsigned msg_len;
843 unsigned num_resp;
844
845 };
846 static struct test tests[] = {
847 {
848 .title = "Attach Request (invalid MI length)",
849 .msg = attach_req_inv_mi_len,
850 .msg_len = sizeof(attach_req_inv_mi_len),
851 .num_resp = 1 /* Reject */
852
853 },
854 {
855 .title = "Attach Request (invalid MI type)",
856 .msg = attach_req_inv_mi_type,
857 .msg_len = sizeof(attach_req_inv_mi_type),
858 .num_resp = 1 /* Reject */
859 },
860 {
861 .title = "Routing Area Update Request (valid)",
862 .msg = dtap_ra_upd_req,
863 .msg_len = sizeof(dtap_ra_upd_req),
864 .num_resp = 2 /* XID Reset + Reject */
865 },
866 {
867 .title = "Routing Area Update Request (invalid type)",
868 .msg = dtap_ra_upd_req_inv_type,
869 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
870 .num_resp = 1 /* Reject */
871 },
872 {
873 .title = "Routing Area Update Request (invalid CAP length)",
874 .msg = dtap_ra_upd_req_inv_cap_len,
875 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
876 .num_resp = 1 /* Reject */
877 },
878 };
879
880 printf("Testing GMM reject\n");
881
882 /* reset the PRNG used by sgsn_alloc_ptmsi */
883 srand(1);
884
885 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
886
887 OSMO_ASSERT(count(gprs_llme_list()) == 0);
888
889 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
890 const struct test *test = &tests[idx];
891 printf(" - %s\n", test->title);
892
893 /* Create a LLE/LLME */
894 lle = gprs_lle_get_or_create(foreign_tlli, 3);
895 OSMO_ASSERT(count(gprs_llme_list()) == 1);
896
897 /* Inject the Request message */
898 send_0408_message(lle->llme, foreign_tlli,
899 test->msg, test->msg_len);
900
901 /* We expect a Reject message */
902 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
903 sgsn_tx_counter, test->num_resp);
904 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
905
906 /* verify that LLME/MM are removed */
907 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
908 OSMO_ASSERT(ctx == NULL);
909 OSMO_ASSERT(count(gprs_llme_list()) == 0);
910 }
911}
912
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100913/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +0100914 * Test cancellation of attached MM contexts
915 */
916static void test_gmm_cancel(void)
917{
918 struct gprs_ra_id raid = { 0, };
919 struct sgsn_mm_ctx *ctx = NULL;
920 struct sgsn_mm_ctx *ictx;
921 uint32_t ptmsi1;
922 uint32_t foreign_tlli;
923 uint32_t local_tlli = 0;
924 struct gprs_llc_lle *lle;
925 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
926
927 /* DTAP - Attach Request */
928 /* The P-TMSI is not known by the SGSN */
929 static const unsigned char attach_req[] = {
930 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
931 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
932 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
933 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
934 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
935 };
936
937 /* DTAP - Identity Response IMEI */
938 static const unsigned char ident_resp_imei[] = {
939 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
940 0x56
941 };
942
943 /* DTAP - Identity Response IMSI */
944 static const unsigned char ident_resp_imsi[] = {
945 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
946 0x54
947 };
948
949 /* DTAP - Attach Complete */
950 static const unsigned char attach_compl[] = {
951 0x08, 0x03
952 };
953
954 printf("Testing cancellation\n");
955
956 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
957
958 /* reset the PRNG used by sgsn_alloc_ptmsi */
959 srand(1);
960
961 ptmsi1 = sgsn_alloc_ptmsi();
962 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
963
964 /* reset the PRNG, so that the same P-TMSI sequence will be generated
965 * again */
966 srand(1);
967
968 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
969
970 /* Create a LLE/LLME */
971 OSMO_ASSERT(count(gprs_llme_list()) == 0);
972 lle = gprs_lle_get_or_create(foreign_tlli, 3);
973 OSMO_ASSERT(count(gprs_llme_list()) == 1);
974
975 /* inject the attach request */
976 send_0408_message(lle->llme, foreign_tlli,
977 attach_req, ARRAY_SIZE(attach_req));
978
979 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
980 OSMO_ASSERT(ctx != NULL);
981 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
982
983 /* we expect an identity request (IMEI) */
984 OSMO_ASSERT(sgsn_tx_counter == 1);
985
986 /* inject the identity response (IMEI) */
987 send_0408_message(ctx->llme, foreign_tlli,
988 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
989
990 /* we expect an identity request (IMSI) */
991 OSMO_ASSERT(sgsn_tx_counter == 1);
992
993 /* inject the identity response (IMSI) */
994 send_0408_message(ctx->llme, foreign_tlli,
995 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
996
997 /* check that the MM context has not been removed due to a failed
998 * authorization */
999 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1000
1001 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1002
1003 /* we expect an attach accept/reject */
1004 OSMO_ASSERT(sgsn_tx_counter == 1);
1005
1006 /* this has been randomly assigned by the SGSN */
1007 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1008
1009 /* inject the attach complete */
1010 send_0408_message(ctx->llme, local_tlli,
1011 attach_compl, ARRAY_SIZE(attach_compl));
1012
1013 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1014
1015 /* we don't expect a response */
1016 OSMO_ASSERT(sgsn_tx_counter == 0);
1017
1018 /* cancel */
1019 gsm0408_gprs_access_cancelled(ctx);
1020
1021 /* verify that things are gone */
1022 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1023 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1024 OSMO_ASSERT(!ictx);
1025
1026 sgsn->cfg.auth_policy = saved_auth_policy;
1027}
1028
1029/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001030 * Test the dynamic allocation of P-TMSIs
1031 */
1032static void test_gmm_ptmsi_allocation(void)
1033{
1034 struct gprs_ra_id raid = { 0, };
1035 struct sgsn_mm_ctx *ctx = NULL;
1036 struct sgsn_mm_ctx *ictx;
1037 uint32_t foreign_tlli;
1038 uint32_t ptmsi1;
1039 uint32_t ptmsi2;
1040 uint32_t old_ptmsi;
1041 uint32_t local_tlli = 0;
1042 struct gprs_llc_lle *lle;
1043 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1044
1045 /* DTAP - Attach Request (IMSI 12131415161718) */
1046 static const unsigned char attach_req[] = {
1047 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1048 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1049 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1050 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1051 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1052 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1053 0x00,
1054 };
1055
1056 /* DTAP - Identity Response IMEI */
1057 static const unsigned char ident_resp_imei[] = {
1058 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1059 0x56
1060 };
1061
1062 /* DTAP - Attach Complete */
1063 static const unsigned char attach_compl[] = {
1064 0x08, 0x03
1065 };
1066
1067 /* DTAP - Routing Area Update Request */
1068 static const unsigned char ra_upd_req[] = {
1069 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1070 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1071 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1072 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1073 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1074 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1075 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1076 };
1077
1078 /* DTAP - Routing Area Update Complete */
1079 static const unsigned char ra_upd_complete[] = {
1080 0x08, 0x0a
1081 };
1082
1083 /* DTAP - Detach Request (MO) */
1084 /* normal detach, power_off = 1 */
1085 static const unsigned char detach_req[] = {
1086 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1087 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1088 };
1089
1090 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1091
1092 printf("Testing P-TMSI allocation\n");
1093
1094 printf(" - sgsn_alloc_ptmsi\n");
1095
1096 /* reset the PRNG used by sgsn_alloc_ptmsi */
1097 srand(1);
1098
1099 ptmsi1 = sgsn_alloc_ptmsi();
1100 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1101
1102 ptmsi2 = sgsn_alloc_ptmsi();
1103 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1104
1105 OSMO_ASSERT(ptmsi1 != ptmsi2);
1106
1107 printf(" - Repeated Attach Request\n");
1108
1109 /* reset the PRNG, so that the same P-TMSI will be generated
1110 * again */
1111 srand(1);
1112
1113 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1114
1115 /* Create a LLE/LLME */
1116 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1117 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1118 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1119
1120 /* inject the attach request */
1121 send_0408_message(lle->llme, foreign_tlli,
1122 attach_req, ARRAY_SIZE(attach_req));
1123
1124 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1125 OSMO_ASSERT(ctx != NULL);
1126 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1127 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1128
1129 old_ptmsi = ctx->p_tmsi_old;
1130
1131 /* we expect an identity request (IMEI) */
1132 OSMO_ASSERT(sgsn_tx_counter == 1);
1133
1134 /* inject the identity response (IMEI) */
1135 send_0408_message(ctx->llme, foreign_tlli,
1136 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1137
1138 /* check that the MM context has not been removed due to a failed
1139 * authorization */
1140 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1141
1142 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1143 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1144
1145 /* we expect an attach accept */
1146 OSMO_ASSERT(sgsn_tx_counter == 1);
1147
1148 /* we ignore this and send the attach again */
1149 send_0408_message(lle->llme, foreign_tlli,
1150 attach_req, ARRAY_SIZE(attach_req));
1151
1152 /* the allocated P-TMSI should be the same */
1153 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1154 OSMO_ASSERT(ctx != NULL);
1155 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1156 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1157 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1158
1159 /* inject the attach complete */
1160 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1161 send_0408_message(ctx->llme, local_tlli,
1162 attach_compl, ARRAY_SIZE(attach_compl));
1163
1164 /* we don't expect a response */
1165 OSMO_ASSERT(sgsn_tx_counter == 0);
1166
1167 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1168 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1169 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1170
1171 printf(" - Repeated RA Update Request\n");
1172
1173 /* inject the RA update request */
1174 send_0408_message(ctx->llme, local_tlli,
1175 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1176
1177 /* we expect an RA update accept */
1178 OSMO_ASSERT(sgsn_tx_counter == 1);
1179
1180 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1181 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1182 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1183
1184 /* repeat the RA update request */
1185 send_0408_message(ctx->llme, local_tlli,
1186 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1187
1188 /* we expect an RA update accept */
1189 OSMO_ASSERT(sgsn_tx_counter == 1);
1190
1191 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1192 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1193 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1194
1195 /* inject the RA update complete */
1196 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1197 send_0408_message(ctx->llme, local_tlli,
1198 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1199
1200 /* we don't expect a response */
1201 OSMO_ASSERT(sgsn_tx_counter == 0);
1202
1203 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1204 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1205 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1206
1207 /* inject the detach */
1208 send_0408_message(ctx->llme, local_tlli,
1209 detach_req, ARRAY_SIZE(detach_req));
1210
1211 /* verify that things are gone */
1212 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1213 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1214 OSMO_ASSERT(!ictx);
1215
1216 sgsn->cfg.auth_policy = saved_auth_policy;
1217}
1218
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001219static struct log_info_cat gprs_categories[] = {
1220 [DMM] = {
1221 .name = "DMM",
1222 .description = "Layer3 Mobility Management (MM)",
1223 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001224 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001225 },
1226 [DPAG] = {
1227 .name = "DPAG",
1228 .description = "Paging Subsystem",
1229 .color = "\033[1;38m",
1230 .enabled = 1, .loglevel = LOGL_NOTICE,
1231 },
1232 [DMEAS] = {
1233 .name = "DMEAS",
1234 .description = "Radio Measurement Processing",
1235 .enabled = 0, .loglevel = LOGL_NOTICE,
1236 },
1237 [DREF] = {
1238 .name = "DREF",
1239 .description = "Reference Counting",
1240 .enabled = 0, .loglevel = LOGL_NOTICE,
1241 },
1242 [DGPRS] = {
1243 .name = "DGPRS",
1244 .description = "GPRS Packet Service",
1245 .enabled = 1, .loglevel = LOGL_DEBUG,
1246 },
1247 [DNS] = {
1248 .name = "DNS",
1249 .description = "GPRS Network Service (NS)",
1250 .enabled = 1, .loglevel = LOGL_INFO,
1251 },
1252 [DBSSGP] = {
1253 .name = "DBSSGP",
1254 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1255 .enabled = 1, .loglevel = LOGL_DEBUG,
1256 },
1257 [DLLC] = {
1258 .name = "DLLC",
1259 .description = "GPRS Logical Link Control Protocol (LLC)",
1260 .enabled = 1, .loglevel = LOGL_DEBUG,
1261 },
1262 [DSNDCP] = {
1263 .name = "DSNDCP",
1264 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1265 .enabled = 1, .loglevel = LOGL_DEBUG,
1266 },
1267};
1268
1269static struct log_info info = {
1270 .cat = gprs_categories,
1271 .num_cat = ARRAY_SIZE(gprs_categories),
1272};
1273
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001274int main(int argc, char **argv)
1275{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001276 osmo_init_logging(&info);
1277 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1278 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1279
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001280 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001281 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001282
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001283 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001284 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001285 test_auth_triplets();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001286 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001287 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001288 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001289 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001290 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001291 test_gmm_attach_acl();
1292 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001293 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001294 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001295 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001296 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001297 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001298 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001299 return 0;
1300}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001301
1302
1303/* stubs */
1304struct osmo_prim_hdr;
1305int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1306{
1307 abort();
1308}