blob: 2eb6f388f03a02f9b145426306df36d1add337d7 [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
70
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020071static int count(struct llist_head *head)
72{
73 struct llist_head *cur;
74 int count = 0;
75
76 llist_for_each(cur, head)
77 count += 1;
78
79 return count;
80}
81
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020082static struct msgb *create_msg(const uint8_t *data, size_t len)
83{
84 struct msgb *msg = msgb_alloc(len + 8, "test message");
85 msg->l1h = msgb_put(msg, 8);
86 msg->l2h = msgb_put(msg, len);
87 memcpy(msg->l2h, data, len);
88
89 msgb_bcid(msg) = msg->l1h;
90 msgb_gmmh(msg) = msg->l2h;
91 return msg;
92}
93
Jacob Erlbeckabc16a52014-10-27 13:23:49 +010094/*
95 * Create a context and search for it
96 */
97static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
98{
99 struct sgsn_mm_ctx *ctx, *ictx;
100 struct gprs_llc_lle *lle;
101 int old_count = count(gprs_llme_list());
102
103 lle = gprs_lle_get_or_create(tlli, 3);
104 ctx = sgsn_mm_ctx_alloc(tlli, raid);
105 ctx->mm_state = GMM_REGISTERED_NORMAL;
106 ctx->llme = lle->llme;
107
108 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
109 OSMO_ASSERT(ictx == ctx);
110
111 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
112
113 return ctx;
114}
115
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100116static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
117 const uint8_t *data, size_t data_len)
118{
119 struct msgb *msg;
120
121 sgsn_tx_counter = 0;
122
123 msg = create_msg(data, data_len);
124 msgb_tlli(msg) = tlli;
125 gsm0408_gprs_rcvmsg(msg, llme);
126 msgb_free(msg);
127}
128
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200129static void test_llme(void)
130{
131 struct gprs_llc_lle *lle, *lle_copy;
132 uint32_t local_tlli;
133 uint32_t foreign_tlli;
134
135 printf("Testing LLME allocations\n");
136 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
137 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
138
139 /* initial state */
140 OSMO_ASSERT(count(gprs_llme_list()) == 0);
141
142 /* Create a new entry */
143 lle = gprs_lle_get_or_create(local_tlli, 3);
144 OSMO_ASSERT(lle);
145 OSMO_ASSERT(count(gprs_llme_list()) == 1);
146
147 /* No new entry is created */
148 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
149 OSMO_ASSERT(lle == lle_copy);
150 OSMO_ASSERT(count(gprs_llme_list()) == 1);
151 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
152 OSMO_ASSERT(lle == lle_copy);
153 OSMO_ASSERT(count(gprs_llme_list()) == 1);
154
155 /* unassign which should delete it*/
156 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
157
158 /* Check that everything was cleaned up */
159 OSMO_ASSERT(count(gprs_llme_list()) == 0);
160}
161
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100162struct gsm_subscriber *last_updated_subscr = NULL;
163void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
164 struct gsm_subscriber *subscr)
165{
166 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
167 __func__, mmctx, subscr);
168 last_updated_subscr = subscr;
169}
170
171static void test_subscriber(void)
172{
173 struct gsm_subscriber *s1, *s2, *s1found, *s2found;
174 const char *imsi1 = "1234567890";
175 const char *imsi2 = "9876543210";
176
177 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
178
179 printf("Testing core subscriber data API\n");
180
181 /* Check for emptiness */
182 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
183 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
184
185 /* Allocate entry 1 */
186 s1 = gprs_subscr_get_or_create(imsi1);
187 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
188 s1found = gprs_subscr_get_by_imsi(imsi1);
189 OSMO_ASSERT(s1found == s1);
190 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
191 subscr_put(s1found);
192
193 /* Allocate entry 2 */
194 s2 = gprs_subscr_get_or_create(imsi2);
195 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
196 s1found = gprs_subscr_get_by_imsi(imsi1);
197 s2found = gprs_subscr_get_by_imsi(imsi2);
198 OSMO_ASSERT(s1found == s1);
199 OSMO_ASSERT(s2found == s2);
200 subscr_put(s1found);
201 subscr_put(s2found);
202
203 /* Update entry 1 */
204 last_updated_subscr = NULL;
205 gprs_subscr_update(s1);
206 OSMO_ASSERT(last_updated_subscr == s1);
207
208 /* Because of the update, it won't be freed on delete now */
209 gprs_subscr_delete(s1);
210 s1found = gprs_subscr_get_by_imsi(imsi1);
211 OSMO_ASSERT(s1found != NULL);
212 s1 = s1found;
213
214 /* Cancel it, so that delete will free it.
215 * Refcount it to make sure s1 won't be freed here */
216 last_updated_subscr = NULL;
217 gprs_subscr_put_and_cancel(subscr_get(s1));
218 OSMO_ASSERT(last_updated_subscr == s1);
219
220 /* Cancelled entries are still being found */
221 s1found = gprs_subscr_get_by_imsi(imsi1);
222 OSMO_ASSERT(s1found != NULL);
223 subscr_put(s1found);
224
225 /* Free entry 1 */
226 gprs_subscr_delete(s1);
227 s1 = NULL;
228 s2found = gprs_subscr_get_by_imsi(imsi2);
229 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
230 OSMO_ASSERT(s2found == s2);
231 subscr_put(s2found);
232
233 /* Free entry 2 */
234 gprs_subscr_delete(s2);
235 s2 = NULL;
236 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
237 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
238
239 OSMO_ASSERT(llist_empty(&active_subscribers));
240
241 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
242}
243
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200244/*
245 * Test that a GMM Detach will remove the MMCTX and the
246 * associated LLME.
247 */
248static void test_gmm_detach(void)
249{
250 struct gprs_ra_id raid = { 0, };
251 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200252 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200253
254 printf("Testing GMM detach\n");
255
256 /* DTAP - Detach Request (MO) */
257 /* normal detach, power_off = 0 */
258 static const unsigned char detach_req[] = {
259 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
260 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
261 };
262
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200263 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200264
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100265 /* Create a context */
266 OSMO_ASSERT(count(gprs_llme_list()) == 0);
267 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200268
269 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100270 send_0408_message(ctx->llme, local_tlli,
271 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200272
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100273 /* verify that a single message (hopefully the Detach Accept) has been
274 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100275 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100276
277 /* verify that things are gone */
278 OSMO_ASSERT(count(gprs_llme_list()) == 0);
279 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
280 OSMO_ASSERT(!ictx);
281}
282
283/*
284 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
285 * will not sent a Detach Accept message (power_off = 1)
286 */
287static void test_gmm_detach_power_off(void)
288{
289 struct gprs_ra_id raid = { 0, };
290 struct sgsn_mm_ctx *ctx, *ictx;
291 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100292
293 printf("Testing GMM detach (power off)\n");
294
295 /* DTAP - Detach Request (MO) */
296 /* normal detach, power_off = 1 */
297 static const unsigned char detach_req[] = {
298 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
299 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
300 };
301
302 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
303
304 /* Create a context */
305 OSMO_ASSERT(count(gprs_llme_list()) == 0);
306 ctx = alloc_mm_ctx(local_tlli, &raid);
307
308 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100309 send_0408_message(ctx->llme, local_tlli,
310 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100311
312 /* verify that no message (and therefore no Detach Accept) has been
313 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100314 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100315
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200316 /* verify that things are gone */
317 OSMO_ASSERT(count(gprs_llme_list()) == 0);
318 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200319 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200320}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200321
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200322/*
323 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
324 */
325static void test_gmm_detach_no_mmctx(void)
326{
327 struct gprs_llc_lle *lle;
328 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200329
330 printf("Testing GMM detach (no MMCTX)\n");
331
332 /* DTAP - Detach Request (MO) */
333 /* normal detach, power_off = 0 */
334 static const unsigned char detach_req[] = {
335 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
336 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
337 };
338
339 /* Create an LLME */
340 OSMO_ASSERT(count(gprs_llme_list()) == 0);
341 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
342 lle = gprs_lle_get_or_create(local_tlli, 3);
343
344 OSMO_ASSERT(count(gprs_llme_list()) == 1);
345
346 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100347 send_0408_message(lle->llme, local_tlli,
348 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200349
350 /* verify that the LLME is gone */
351 OSMO_ASSERT(count(gprs_llme_list()) == 0);
352}
353
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100354/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100355 * Test that a single GMM Detach Accept message will not cause the SGSN to send
356 * any message or leave an MM context at the SGSN.
357 */
358static void test_gmm_detach_accept_unexpected(void)
359{
360 struct gprs_llc_lle *lle;
361 uint32_t local_tlli;
362
363 printf("Testing GMM detach accept (unexpected)\n");
364
365 /* DTAP - Detach Accept (MT) */
366 /* normal detach */
367 static const unsigned char detach_acc[] = {
368 0x08, 0x06
369 };
370
371 /* Create an LLME */
372 OSMO_ASSERT(count(gprs_llme_list()) == 0);
373 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
374 lle = gprs_lle_get_or_create(local_tlli, 3);
375
376 /* inject the detach */
377 send_0408_message(lle->llme, local_tlli,
378 detach_acc, ARRAY_SIZE(detach_acc));
379
380 /* verify that no message (and therefore no Status or XID reset) has been
381 * sent by the SGSN */
382 OSMO_ASSERT(sgsn_tx_counter == 0);
383
384 /* verify that things are gone */
385 OSMO_ASSERT(count(gprs_llme_list()) == 0);
386}
387
388/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100389 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
390 */
391static void test_gmm_status_no_mmctx(void)
392{
393 struct gprs_llc_lle *lle;
394 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100395
396 printf("Testing GMM Status (no MMCTX)\n");
397
398 /* DTAP - GMM Status, protocol error */
399 static const unsigned char gmm_status[] = {
400 0x08, 0x20, 0x6f
401 };
402
403 /* Create an LLME */
404 OSMO_ASSERT(count(gprs_llme_list()) == 0);
405 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
406 lle = gprs_lle_get_or_create(local_tlli, 3);
407
408 OSMO_ASSERT(count(gprs_llme_list()) == 1);
409
410 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100411 send_0408_message(lle->llme, local_tlli,
412 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100413
414 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100415 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100416
417 /* verify that the LLME is gone */
418 OSMO_ASSERT(count(gprs_llme_list()) == 0);
419}
420
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100421/*
422 * Test the GMM Attach procedure
423 */
424static void test_gmm_attach(void)
425{
426 struct gprs_ra_id raid = { 0, };
427 struct sgsn_mm_ctx *ctx = NULL;
428 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100429 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100430 uint32_t foreign_tlli;
431 uint32_t local_tlli = 0;
432 struct gprs_llc_lle *lle;
433
434 /* DTAP - Attach Request */
435 /* The P-TMSI is not known by the SGSN */
436 static const unsigned char attach_req[] = {
437 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
438 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
439 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
440 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
441 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
442 };
443
444 /* DTAP - Identity Response IMEI */
445 static const unsigned char ident_resp_imei[] = {
446 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
447 0x56
448 };
449
450 /* DTAP - Identity Response IMSI */
451 static const unsigned char ident_resp_imsi[] = {
452 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
453 0x54
454 };
455
456 /* DTAP - Attach Complete */
457 static const unsigned char attach_compl[] = {
458 0x08, 0x03
459 };
460
461 /* DTAP - Detach Request (MO) */
462 /* normal detach, power_off = 0 */
463 static const unsigned char detach_req[] = {
464 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
465 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
466 };
467
468 printf("Testing GMM attach\n");
469
470 /* reset the PRNG used by sgsn_alloc_ptmsi */
471 srand(1);
472
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100473 ptmsi1 = sgsn_alloc_ptmsi();
474 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
475
476 /* reset the PRNG, so that the same P-TMSI sequence will be generated
477 * again */
478 srand(1);
479
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100480 sgsn_acl_add("123456789012345", &sgsn->cfg);
481
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100482 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
483
484 /* Create a LLE/LLME */
485 OSMO_ASSERT(count(gprs_llme_list()) == 0);
486 lle = gprs_lle_get_or_create(foreign_tlli, 3);
487 OSMO_ASSERT(count(gprs_llme_list()) == 1);
488
489 /* inject the attach request */
490 send_0408_message(lle->llme, foreign_tlli,
491 attach_req, ARRAY_SIZE(attach_req));
492
493 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
494 OSMO_ASSERT(ctx != NULL);
495 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
496
497 /* we expect an identity request (IMEI) */
498 OSMO_ASSERT(sgsn_tx_counter == 1);
499
500 /* inject the identity response (IMEI) */
501 send_0408_message(ctx->llme, foreign_tlli,
502 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
503
504 /* we expect an identity request (IMSI) */
505 OSMO_ASSERT(sgsn_tx_counter == 1);
506
507 /* inject the identity response (IMSI) */
508 send_0408_message(ctx->llme, foreign_tlli,
509 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
510
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100511 /* check that the MM context has not been removed due to a failed
512 * authorization */
513 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
514
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100515 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100516
517 /* we expect an attach accept/reject */
518 OSMO_ASSERT(sgsn_tx_counter == 1);
519
520 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100521 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100522
523 /* inject the attach complete */
524 send_0408_message(ctx->llme, local_tlli,
525 attach_compl, ARRAY_SIZE(attach_compl));
526
527 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
528
529 /* we don't expect a response */
530 OSMO_ASSERT(sgsn_tx_counter == 0);
531
532 /* inject the detach */
533 send_0408_message(ctx->llme, local_tlli,
534 detach_req, ARRAY_SIZE(detach_req));
535
536 /* verify that things are gone */
537 OSMO_ASSERT(count(gprs_llme_list()) == 0);
538 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
539 OSMO_ASSERT(!ictx);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100540
541 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100542}
543
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100544/*
545 * Test the GMM Rejects
546 */
547static void test_gmm_reject(void)
548{
549 struct gprs_ra_id raid = { 0, };
550 struct sgsn_mm_ctx *ctx = NULL;
551 uint32_t foreign_tlli;
552 struct gprs_llc_lle *lle;
553 int idx;
554
555 /* DTAP - Attach Request */
556 /* Invalid MI length */
557 static const unsigned char attach_req_inv_mi_len[] = {
558 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
559 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
560 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
561 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
562 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
563 };
564
565 /* DTAP - Attach Request */
566 /* Invalid MI type (IMEI) */
567 static const unsigned char attach_req_inv_mi_type[] = {
568 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
569 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
570 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
571 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
572 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
573 };
574
575 /* DTAP - Routing Area Update Request */
576 static const unsigned char dtap_ra_upd_req[] = {
577 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
578 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
579 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
580 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
581 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
582 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
583 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
584 };
585
586 /* DTAP - Routing Area Update Request */
587 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
588 static const unsigned char dtap_ra_upd_req_inv_type[] = {
589 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
590 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
591 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
592 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
593 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
594 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
595 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
596 };
597
598 /* DTAP - Routing Area Update Request */
599 /* Invalid cap length */
600 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
601 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
602 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
603 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
604 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
605 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
606 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
607 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
608 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
609 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
610 };
611
612 struct test {
613 const char *title;
614 const unsigned char *msg;
615 unsigned msg_len;
616 unsigned num_resp;
617
618 };
619 static struct test tests[] = {
620 {
621 .title = "Attach Request (invalid MI length)",
622 .msg = attach_req_inv_mi_len,
623 .msg_len = sizeof(attach_req_inv_mi_len),
624 .num_resp = 1 /* Reject */
625
626 },
627 {
628 .title = "Attach Request (invalid MI type)",
629 .msg = attach_req_inv_mi_type,
630 .msg_len = sizeof(attach_req_inv_mi_type),
631 .num_resp = 1 /* Reject */
632 },
633 {
634 .title = "Routing Area Update Request (valid)",
635 .msg = dtap_ra_upd_req,
636 .msg_len = sizeof(dtap_ra_upd_req),
637 .num_resp = 2 /* XID Reset + Reject */
638 },
639 {
640 .title = "Routing Area Update Request (invalid type)",
641 .msg = dtap_ra_upd_req_inv_type,
642 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
643 .num_resp = 1 /* Reject */
644 },
645 {
646 .title = "Routing Area Update Request (invalid CAP length)",
647 .msg = dtap_ra_upd_req_inv_cap_len,
648 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
649 .num_resp = 1 /* Reject */
650 },
651 };
652
653 printf("Testing GMM reject\n");
654
655 /* reset the PRNG used by sgsn_alloc_ptmsi */
656 srand(1);
657
658 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
659
660 OSMO_ASSERT(count(gprs_llme_list()) == 0);
661
662 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
663 const struct test *test = &tests[idx];
664 printf(" - %s\n", test->title);
665
666 /* Create a LLE/LLME */
667 lle = gprs_lle_get_or_create(foreign_tlli, 3);
668 OSMO_ASSERT(count(gprs_llme_list()) == 1);
669
670 /* Inject the Request message */
671 send_0408_message(lle->llme, foreign_tlli,
672 test->msg, test->msg_len);
673
674 /* We expect a Reject message */
675 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
676 sgsn_tx_counter, test->num_resp);
677 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
678
679 /* verify that LLME/MM are removed */
680 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
681 OSMO_ASSERT(ctx == NULL);
682 OSMO_ASSERT(count(gprs_llme_list()) == 0);
683 }
684}
685
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100686/*
687 * Test the dynamic allocation of P-TMSIs
688 */
689static void test_gmm_ptmsi_allocation(void)
690{
691 struct gprs_ra_id raid = { 0, };
692 struct sgsn_mm_ctx *ctx = NULL;
693 struct sgsn_mm_ctx *ictx;
694 uint32_t foreign_tlli;
695 uint32_t ptmsi1;
696 uint32_t ptmsi2;
697 uint32_t old_ptmsi;
698 uint32_t local_tlli = 0;
699 struct gprs_llc_lle *lle;
700 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
701
702 /* DTAP - Attach Request (IMSI 12131415161718) */
703 static const unsigned char attach_req[] = {
704 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
705 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
706 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
707 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
708 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
709 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
710 0x00,
711 };
712
713 /* DTAP - Identity Response IMEI */
714 static const unsigned char ident_resp_imei[] = {
715 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
716 0x56
717 };
718
719 /* DTAP - Attach Complete */
720 static const unsigned char attach_compl[] = {
721 0x08, 0x03
722 };
723
724 /* DTAP - Routing Area Update Request */
725 static const unsigned char ra_upd_req[] = {
726 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
727 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
728 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
729 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
730 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
731 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
732 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
733 };
734
735 /* DTAP - Routing Area Update Complete */
736 static const unsigned char ra_upd_complete[] = {
737 0x08, 0x0a
738 };
739
740 /* DTAP - Detach Request (MO) */
741 /* normal detach, power_off = 1 */
742 static const unsigned char detach_req[] = {
743 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
744 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
745 };
746
747 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
748
749 printf("Testing P-TMSI allocation\n");
750
751 printf(" - sgsn_alloc_ptmsi\n");
752
753 /* reset the PRNG used by sgsn_alloc_ptmsi */
754 srand(1);
755
756 ptmsi1 = sgsn_alloc_ptmsi();
757 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
758
759 ptmsi2 = sgsn_alloc_ptmsi();
760 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
761
762 OSMO_ASSERT(ptmsi1 != ptmsi2);
763
764 printf(" - Repeated Attach Request\n");
765
766 /* reset the PRNG, so that the same P-TMSI will be generated
767 * again */
768 srand(1);
769
770 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
771
772 /* Create a LLE/LLME */
773 OSMO_ASSERT(count(gprs_llme_list()) == 0);
774 lle = gprs_lle_get_or_create(foreign_tlli, 3);
775 OSMO_ASSERT(count(gprs_llme_list()) == 1);
776
777 /* inject the attach request */
778 send_0408_message(lle->llme, foreign_tlli,
779 attach_req, ARRAY_SIZE(attach_req));
780
781 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
782 OSMO_ASSERT(ctx != NULL);
783 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
784 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
785
786 old_ptmsi = ctx->p_tmsi_old;
787
788 /* we expect an identity request (IMEI) */
789 OSMO_ASSERT(sgsn_tx_counter == 1);
790
791 /* inject the identity response (IMEI) */
792 send_0408_message(ctx->llme, foreign_tlli,
793 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
794
795 /* check that the MM context has not been removed due to a failed
796 * authorization */
797 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
798
799 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
800 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
801
802 /* we expect an attach accept */
803 OSMO_ASSERT(sgsn_tx_counter == 1);
804
805 /* we ignore this and send the attach again */
806 send_0408_message(lle->llme, foreign_tlli,
807 attach_req, ARRAY_SIZE(attach_req));
808
809 /* the allocated P-TMSI should be the same */
810 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
811 OSMO_ASSERT(ctx != NULL);
812 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
813 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
814 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
815
816 /* inject the attach complete */
817 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
818 send_0408_message(ctx->llme, local_tlli,
819 attach_compl, ARRAY_SIZE(attach_compl));
820
821 /* we don't expect a response */
822 OSMO_ASSERT(sgsn_tx_counter == 0);
823
824 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
825 OSMO_ASSERT(ctx->p_tmsi_old == 0);
826 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
827
828 printf(" - Repeated RA Update Request\n");
829
830 /* inject the RA update request */
831 send_0408_message(ctx->llme, local_tlli,
832 ra_upd_req, ARRAY_SIZE(ra_upd_req));
833
834 /* we expect an RA update accept */
835 OSMO_ASSERT(sgsn_tx_counter == 1);
836
837 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
838 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
839 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
840
841 /* repeat the RA update request */
842 send_0408_message(ctx->llme, local_tlli,
843 ra_upd_req, ARRAY_SIZE(ra_upd_req));
844
845 /* we expect an RA update accept */
846 OSMO_ASSERT(sgsn_tx_counter == 1);
847
848 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
849 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
850 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
851
852 /* inject the RA update complete */
853 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
854 send_0408_message(ctx->llme, local_tlli,
855 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
856
857 /* we don't expect a response */
858 OSMO_ASSERT(sgsn_tx_counter == 0);
859
860 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
861 OSMO_ASSERT(ctx->p_tmsi_old == 0);
862 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
863
864 /* inject the detach */
865 send_0408_message(ctx->llme, local_tlli,
866 detach_req, ARRAY_SIZE(detach_req));
867
868 /* verify that things are gone */
869 OSMO_ASSERT(count(gprs_llme_list()) == 0);
870 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
871 OSMO_ASSERT(!ictx);
872
873 sgsn->cfg.auth_policy = saved_auth_policy;
874}
875
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200876static struct log_info_cat gprs_categories[] = {
877 [DMM] = {
878 .name = "DMM",
879 .description = "Layer3 Mobility Management (MM)",
880 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100881 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200882 },
883 [DPAG] = {
884 .name = "DPAG",
885 .description = "Paging Subsystem",
886 .color = "\033[1;38m",
887 .enabled = 1, .loglevel = LOGL_NOTICE,
888 },
889 [DMEAS] = {
890 .name = "DMEAS",
891 .description = "Radio Measurement Processing",
892 .enabled = 0, .loglevel = LOGL_NOTICE,
893 },
894 [DREF] = {
895 .name = "DREF",
896 .description = "Reference Counting",
897 .enabled = 0, .loglevel = LOGL_NOTICE,
898 },
899 [DGPRS] = {
900 .name = "DGPRS",
901 .description = "GPRS Packet Service",
902 .enabled = 1, .loglevel = LOGL_DEBUG,
903 },
904 [DNS] = {
905 .name = "DNS",
906 .description = "GPRS Network Service (NS)",
907 .enabled = 1, .loglevel = LOGL_INFO,
908 },
909 [DBSSGP] = {
910 .name = "DBSSGP",
911 .description = "GPRS BSS Gateway Protocol (BSSGP)",
912 .enabled = 1, .loglevel = LOGL_DEBUG,
913 },
914 [DLLC] = {
915 .name = "DLLC",
916 .description = "GPRS Logical Link Control Protocol (LLC)",
917 .enabled = 1, .loglevel = LOGL_DEBUG,
918 },
919 [DSNDCP] = {
920 .name = "DSNDCP",
921 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
922 .enabled = 1, .loglevel = LOGL_DEBUG,
923 },
924};
925
926static struct log_info info = {
927 .cat = gprs_categories,
928 .num_cat = ARRAY_SIZE(gprs_categories),
929};
930
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200931int main(int argc, char **argv)
932{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200933 osmo_init_logging(&info);
934 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
935 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
936
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +0100937 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100938 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100939
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200940 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100941 test_subscriber();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200942 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100943 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200944 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100945 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100946 test_gmm_status_no_mmctx();
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100947 test_gmm_attach();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100948 test_gmm_reject();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100949 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200950 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200951 return 0;
952}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200953
954
955/* stubs */
956struct osmo_prim_hdr;
957int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
958{
959 abort();
960}