blob: ba76f55753187aa0fa6fb466617ad413a058cfdd [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>
Jacob Erlbeckbce20612015-01-05 18:57:32 +010031#include <openbsc/gsm_04_08_gprs.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020032
33#include <osmocom/core/application.h>
34#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010035#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020036
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020037#include <stdio.h>
38
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020039extern void *tall_msgb_ctx;
40
41void *tall_bsc_ctx;
42static struct sgsn_instance sgsn_inst = {
43 .config_file = "osmo_sgsn.cfg",
44 .cfg = {
45 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010046 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020047 },
48};
49struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010050unsigned sgsn_tx_counter = 0;
51
52/* override */
53int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
54 struct bssgp_dl_ud_par *dup)
55{
56 sgsn_tx_counter += 1;
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +010057 msgb_free(msg);
Jacob Erlbeck189999d2014-10-27 14:34:13 +010058 return 0;
59}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020060
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010061/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
62void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *, struct gsm_subscriber *);
63void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *, struct gsm_subscriber *) =
64 &__real_sgsn_update_subscriber_data;
65
66void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
67 struct gsm_subscriber *subscr)
68{
69 (*update_subscriber_data_cb)(mmctx, subscr);
70}
71
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010072/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
73int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
74int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
75 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010076
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010077int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
78 return (*subscr_request_update_location_cb)(mmctx);
79};
80
81/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
82int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
83int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
84 &__real_gprs_subscr_request_auth_info;
85
86int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
87 return (*subscr_request_auth_info_cb)(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010088};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010089
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020090static int count(struct llist_head *head)
91{
92 struct llist_head *cur;
93 int count = 0;
94
95 llist_for_each(cur, head)
96 count += 1;
97
98 return count;
99}
100
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200101static struct msgb *create_msg(const uint8_t *data, size_t len)
102{
103 struct msgb *msg = msgb_alloc(len + 8, "test message");
104 msg->l1h = msgb_put(msg, 8);
105 msg->l2h = msgb_put(msg, len);
106 memcpy(msg->l2h, data, len);
107
108 msgb_bcid(msg) = msg->l1h;
109 msgb_gmmh(msg) = msg->l2h;
110 return msg;
111}
112
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100113/*
114 * Create a context and search for it
115 */
116static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
117{
118 struct sgsn_mm_ctx *ctx, *ictx;
119 struct gprs_llc_lle *lle;
120 int old_count = count(gprs_llme_list());
121
122 lle = gprs_lle_get_or_create(tlli, 3);
123 ctx = sgsn_mm_ctx_alloc(tlli, raid);
124 ctx->mm_state = GMM_REGISTERED_NORMAL;
125 ctx->llme = lle->llme;
126
127 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
128 OSMO_ASSERT(ictx == ctx);
129
130 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
131
132 return ctx;
133}
134
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100135static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
136 const uint8_t *data, size_t data_len)
137{
138 struct msgb *msg;
139
140 sgsn_tx_counter = 0;
141
142 msg = create_msg(data, data_len);
143 msgb_tlli(msg) = tlli;
144 gsm0408_gprs_rcvmsg(msg, llme);
145 msgb_free(msg);
146}
147
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200148static void test_llme(void)
149{
150 struct gprs_llc_lle *lle, *lle_copy;
151 uint32_t local_tlli;
152 uint32_t foreign_tlli;
153
154 printf("Testing LLME allocations\n");
155 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
156 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
157
158 /* initial state */
159 OSMO_ASSERT(count(gprs_llme_list()) == 0);
160
161 /* Create a new entry */
162 lle = gprs_lle_get_or_create(local_tlli, 3);
163 OSMO_ASSERT(lle);
164 OSMO_ASSERT(count(gprs_llme_list()) == 1);
165
166 /* No new entry is created */
167 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
168 OSMO_ASSERT(lle == lle_copy);
169 OSMO_ASSERT(count(gprs_llme_list()) == 1);
170 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
171 OSMO_ASSERT(lle == lle_copy);
172 OSMO_ASSERT(count(gprs_llme_list()) == 1);
173
174 /* unassign which should delete it*/
175 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
176
177 /* Check that everything was cleaned up */
178 OSMO_ASSERT(count(gprs_llme_list()) == 0);
179}
180
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100181struct gsm_subscriber *last_updated_subscr = NULL;
182void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
183 struct gsm_subscriber *subscr)
184{
185 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
186 __func__, mmctx, subscr);
187 last_updated_subscr = subscr;
188}
189
190static void test_subscriber(void)
191{
192 struct gsm_subscriber *s1, *s2, *s1found, *s2found;
193 const char *imsi1 = "1234567890";
194 const char *imsi2 = "9876543210";
195
196 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
197
198 printf("Testing core subscriber data API\n");
199
200 /* Check for emptiness */
201 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
202 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
203
204 /* Allocate entry 1 */
205 s1 = gprs_subscr_get_or_create(imsi1);
206 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
207 s1found = gprs_subscr_get_by_imsi(imsi1);
208 OSMO_ASSERT(s1found == s1);
209 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
210 subscr_put(s1found);
211
212 /* Allocate entry 2 */
213 s2 = gprs_subscr_get_or_create(imsi2);
214 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
215 s1found = gprs_subscr_get_by_imsi(imsi1);
216 s2found = gprs_subscr_get_by_imsi(imsi2);
217 OSMO_ASSERT(s1found == s1);
218 OSMO_ASSERT(s2found == s2);
219 subscr_put(s1found);
220 subscr_put(s2found);
221
222 /* Update entry 1 */
223 last_updated_subscr = NULL;
224 gprs_subscr_update(s1);
225 OSMO_ASSERT(last_updated_subscr == s1);
226
227 /* Because of the update, it won't be freed on delete now */
228 gprs_subscr_delete(s1);
229 s1found = gprs_subscr_get_by_imsi(imsi1);
230 OSMO_ASSERT(s1found != NULL);
231 s1 = s1found;
232
233 /* Cancel it, so that delete will free it.
234 * Refcount it to make sure s1 won't be freed here */
235 last_updated_subscr = NULL;
236 gprs_subscr_put_and_cancel(subscr_get(s1));
237 OSMO_ASSERT(last_updated_subscr == s1);
238
239 /* Cancelled entries are still being found */
240 s1found = gprs_subscr_get_by_imsi(imsi1);
241 OSMO_ASSERT(s1found != NULL);
242 subscr_put(s1found);
243
244 /* Free entry 1 */
245 gprs_subscr_delete(s1);
246 s1 = NULL;
247 s2found = gprs_subscr_get_by_imsi(imsi2);
248 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
249 OSMO_ASSERT(s2found == s2);
250 subscr_put(s2found);
251
252 /* Free entry 2 */
253 gprs_subscr_delete(s2);
254 s2 = NULL;
255 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
256 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
257
258 OSMO_ASSERT(llist_empty(&active_subscribers));
259
260 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
261}
262
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100263static void test_auth_triplets(void)
264{
265 struct gsm_subscriber *s1, *s1found;
266 const char *imsi1 = "1234567890";
267 struct gsm_auth_tuple *at;
268 struct sgsn_mm_ctx *ctx;
269 struct gprs_ra_id raid = { 0, };
270 uint32_t local_tlli = 0xffeeddcc;
271 struct gprs_llc_llme *llme;
272
273 printf("Testing authentication triplet handling\n");
274
275 /* Check for emptiness */
276 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
277
278 /* Allocate entry 1 */
279 s1 = gprs_subscr_get_or_create(imsi1);
280 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
281 s1found = gprs_subscr_get_by_imsi(imsi1);
282 OSMO_ASSERT(s1found == s1);
283 subscr_put(s1found);
284
285 /* Create a context */
286 OSMO_ASSERT(count(gprs_llme_list()) == 0);
287 ctx = alloc_mm_ctx(local_tlli, &raid);
288
289 /* Attach s1 to ctx */
290 ctx->subscr = subscr_get(s1);
291 ctx->subscr->sgsn_data->mm = ctx;
292
293 /* Try to get auth tuple */
294 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
295 OSMO_ASSERT(at == NULL);
296
297 /* Add triplets */
298 s1->sgsn_data->auth_triplets[0].key_seq = 0;
299 s1->sgsn_data->auth_triplets[1].key_seq = 1;
300 s1->sgsn_data->auth_triplets[2].key_seq = 2;
301
302 /* Try to get auth tuple */
303 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
304 OSMO_ASSERT(at != NULL);
305 OSMO_ASSERT(at->key_seq == 0);
306 OSMO_ASSERT(at->use_count == 1);
307 at = sgsn_auth_get_tuple(ctx, at->key_seq);
308 OSMO_ASSERT(at != NULL);
309 OSMO_ASSERT(at->key_seq == 1);
310 OSMO_ASSERT(at->use_count == 1);
311 at = sgsn_auth_get_tuple(ctx, at->key_seq);
312 OSMO_ASSERT(at != NULL);
313 OSMO_ASSERT(at->key_seq == 2);
314 OSMO_ASSERT(at->use_count == 1);
315 at = sgsn_auth_get_tuple(ctx, at->key_seq);
316 OSMO_ASSERT(at == NULL);
317
318 /* Free MM context and subscriber */
319 subscr_put(s1);
320 llme = ctx->llme;
321 sgsn_mm_ctx_free(ctx);
322 s1found = gprs_subscr_get_by_imsi(imsi1);
323 OSMO_ASSERT(s1found == NULL);
324 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
325}
326
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100327#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
328
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100329static int rx_gsup_message(const uint8_t *data, size_t data_len)
330{
331 struct msgb *msg;
332 int rc;
333
334 msg = msgb_alloc(1024, __func__);
335 msg->l2h = msgb_put(msg, data_len);
336 OSMO_ASSERT(msg->l2h != NULL);
337 memcpy(msg->l2h, data, data_len);
338 rc = gprs_subscr_rx_gsup_message(msg);
339 msgb_free(msg);
340
341 return rc;
342}
343
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100344static void test_subscriber_gsup(void)
345{
346 struct gsm_subscriber *s1, *s1found;
347 const char *imsi1 = "1234567890";
348 struct sgsn_mm_ctx *ctx;
349 struct gprs_ra_id raid = { 0, };
350 uint32_t local_tlli = 0xffeeddcc;
351 struct gprs_llc_llme *llme;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100352 int rc;
353
354 static const uint8_t send_auth_info_res[] = {
355 0x0a,
356 TEST_GSUP_IMSI1_IE,
357 0x03, 0x22, /* Auth tuple */
358 0x20, 0x10,
359 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
360 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
361 0x21, 0x04,
362 0x21, 0x22, 0x23, 0x24,
363 0x22, 0x08,
364 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
365 0x03, 0x22, /* Auth tuple */
366 0x20, 0x10,
367 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
368 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
369 0x21, 0x04,
370 0xa1, 0xa2, 0xa3, 0xa4,
371 0x22, 0x08,
372 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
373 };
374
375 static const uint8_t send_auth_info_err[] = {
376 0x09,
377 TEST_GSUP_IMSI1_IE,
378 0x02, 0x01, 0x07 /* GPRS not allowed */
379 };
380
381 static const uint8_t update_location_res[] = {
382 0x06,
383 TEST_GSUP_IMSI1_IE,
384 0x04, 0x00, /* PDP info complete */
385 0x05, 0x12,
386 0x10, 0x01, 0x01,
387 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
388 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
389 0x05, 0x11,
390 0x10, 0x01, 0x02,
391 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
392 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
393 };
394
395 static const uint8_t update_location_err[] = {
396 0x05,
397 TEST_GSUP_IMSI1_IE,
398 0x02, 0x01, 0x07 /* GPRS not allowed */
399 };
400
401 static const uint8_t location_cancellation_req[] = {
402 0x1c,
403 TEST_GSUP_IMSI1_IE,
404 0x06, 0x01, 0x00,
405 };
406
407 printf("Testing subcriber GSUP handling\n");
408
409 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
410
411 /* Check for emptiness */
412 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
413
414 /* Allocate entry 1 */
415 s1 = gprs_subscr_get_or_create(imsi1);
416 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
417 s1found = gprs_subscr_get_by_imsi(imsi1);
418 OSMO_ASSERT(s1found == s1);
419 subscr_put(s1found);
420
421 /* Create a context */
422 OSMO_ASSERT(count(gprs_llme_list()) == 0);
423 ctx = alloc_mm_ctx(local_tlli, &raid);
424 llme = ctx->llme;
425
426 /* Attach s1 to ctx */
427 ctx->subscr = subscr_get(s1);
428 ctx->subscr->sgsn_data->mm = ctx;
429
430 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100431 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100432 OSMO_ASSERT(rc >= 0);
433 OSMO_ASSERT(last_updated_subscr == s1);
434
435 /* Check triplets */
436 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
437 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
438 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
439
440 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100441 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100442 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100443 OSMO_ASSERT(last_updated_subscr == s1);
444
445 /* Check triplets */
446 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
447 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
448 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
449
450 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100451 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100452 OSMO_ASSERT(rc >= 0);
453 OSMO_ASSERT(last_updated_subscr == s1);
454
455 /* Check authorization */
456 OSMO_ASSERT(s1->authorized == 1);
457
458 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100459 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100460 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100461 OSMO_ASSERT(last_updated_subscr == s1);
462
463 /* Check authorization */
464 OSMO_ASSERT(s1->authorized == 0);
465
466 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100467 rc = rx_gsup_message(location_cancellation_req,
468 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100469 OSMO_ASSERT(rc >= 0);
470 OSMO_ASSERT(last_updated_subscr == s1);
471
472 /* Check cancellation result */
473 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
474 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
475
476 /* Free MM context and subscriber */
477 subscr_put(s1);
478 s1found = gprs_subscr_get_by_imsi(imsi1);
479 OSMO_ASSERT(s1found == NULL);
480 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
481
482 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
483}
484
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200485/*
486 * Test that a GMM Detach will remove the MMCTX and the
487 * associated LLME.
488 */
489static void test_gmm_detach(void)
490{
491 struct gprs_ra_id raid = { 0, };
492 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200493 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200494
495 printf("Testing GMM detach\n");
496
497 /* DTAP - Detach Request (MO) */
498 /* normal detach, power_off = 0 */
499 static const unsigned char detach_req[] = {
500 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
501 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
502 };
503
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200504 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200505
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100506 /* Create a context */
507 OSMO_ASSERT(count(gprs_llme_list()) == 0);
508 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200509
510 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100511 send_0408_message(ctx->llme, local_tlli,
512 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200513
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100514 /* verify that a single message (hopefully the Detach Accept) has been
515 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100516 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100517
518 /* verify that things are gone */
519 OSMO_ASSERT(count(gprs_llme_list()) == 0);
520 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
521 OSMO_ASSERT(!ictx);
522}
523
524/*
525 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
526 * will not sent a Detach Accept message (power_off = 1)
527 */
528static void test_gmm_detach_power_off(void)
529{
530 struct gprs_ra_id raid = { 0, };
531 struct sgsn_mm_ctx *ctx, *ictx;
532 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100533
534 printf("Testing GMM detach (power off)\n");
535
536 /* DTAP - Detach Request (MO) */
537 /* normal detach, power_off = 1 */
538 static const unsigned char detach_req[] = {
539 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
540 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
541 };
542
543 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
544
545 /* Create a context */
546 OSMO_ASSERT(count(gprs_llme_list()) == 0);
547 ctx = alloc_mm_ctx(local_tlli, &raid);
548
549 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100550 send_0408_message(ctx->llme, local_tlli,
551 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100552
553 /* verify that no message (and therefore no Detach Accept) has been
554 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100555 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100556
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200557 /* verify that things are gone */
558 OSMO_ASSERT(count(gprs_llme_list()) == 0);
559 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200560 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200561}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200562
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200563/*
564 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
565 */
566static void test_gmm_detach_no_mmctx(void)
567{
568 struct gprs_llc_lle *lle;
569 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200570
571 printf("Testing GMM detach (no MMCTX)\n");
572
573 /* DTAP - Detach Request (MO) */
574 /* normal detach, power_off = 0 */
575 static const unsigned char detach_req[] = {
576 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
577 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
578 };
579
580 /* Create an LLME */
581 OSMO_ASSERT(count(gprs_llme_list()) == 0);
582 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
583 lle = gprs_lle_get_or_create(local_tlli, 3);
584
585 OSMO_ASSERT(count(gprs_llme_list()) == 1);
586
587 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100588 send_0408_message(lle->llme, local_tlli,
589 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200590
591 /* verify that the LLME is gone */
592 OSMO_ASSERT(count(gprs_llme_list()) == 0);
593}
594
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100595/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100596 * Test that a single GMM Detach Accept message will not cause the SGSN to send
597 * any message or leave an MM context at the SGSN.
598 */
599static void test_gmm_detach_accept_unexpected(void)
600{
601 struct gprs_llc_lle *lle;
602 uint32_t local_tlli;
603
604 printf("Testing GMM detach accept (unexpected)\n");
605
606 /* DTAP - Detach Accept (MT) */
607 /* normal detach */
608 static const unsigned char detach_acc[] = {
609 0x08, 0x06
610 };
611
612 /* Create an LLME */
613 OSMO_ASSERT(count(gprs_llme_list()) == 0);
614 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
615 lle = gprs_lle_get_or_create(local_tlli, 3);
616
617 /* inject the detach */
618 send_0408_message(lle->llme, local_tlli,
619 detach_acc, ARRAY_SIZE(detach_acc));
620
621 /* verify that no message (and therefore no Status or XID reset) has been
622 * sent by the SGSN */
623 OSMO_ASSERT(sgsn_tx_counter == 0);
624
625 /* verify that things are gone */
626 OSMO_ASSERT(count(gprs_llme_list()) == 0);
627}
628
629/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100630 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
631 */
632static void test_gmm_status_no_mmctx(void)
633{
634 struct gprs_llc_lle *lle;
635 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100636
637 printf("Testing GMM Status (no MMCTX)\n");
638
639 /* DTAP - GMM Status, protocol error */
640 static const unsigned char gmm_status[] = {
641 0x08, 0x20, 0x6f
642 };
643
644 /* Create an LLME */
645 OSMO_ASSERT(count(gprs_llme_list()) == 0);
646 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
647 lle = gprs_lle_get_or_create(local_tlli, 3);
648
649 OSMO_ASSERT(count(gprs_llme_list()) == 1);
650
651 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100652 send_0408_message(lle->llme, local_tlli,
653 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100654
655 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100656 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100657
658 /* verify that the LLME is gone */
659 OSMO_ASSERT(count(gprs_llme_list()) == 0);
660}
661
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100662/*
663 * Test the GMM Attach procedure
664 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100665static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100666{
667 struct gprs_ra_id raid = { 0, };
668 struct sgsn_mm_ctx *ctx = NULL;
669 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100670 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100671 uint32_t foreign_tlli;
672 uint32_t local_tlli = 0;
673 struct gprs_llc_lle *lle;
674
675 /* DTAP - Attach Request */
676 /* The P-TMSI is not known by the SGSN */
677 static const unsigned char attach_req[] = {
678 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
679 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
680 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
681 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
682 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
683 };
684
685 /* DTAP - Identity Response IMEI */
686 static const unsigned char ident_resp_imei[] = {
687 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
688 0x56
689 };
690
691 /* DTAP - Identity Response IMSI */
692 static const unsigned char ident_resp_imsi[] = {
693 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
694 0x54
695 };
696
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100697 /* DTAP - Authentication and Ciphering Resp */
698 static const unsigned char auth_ciph_resp[] = {
699 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
700 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
701 };
702
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100703 /* DTAP - Attach Complete */
704 static const unsigned char attach_compl[] = {
705 0x08, 0x03
706 };
707
708 /* DTAP - Detach Request (MO) */
709 /* normal detach, power_off = 0 */
710 static const unsigned char detach_req[] = {
711 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
712 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
713 };
714
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100715 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100716
717 /* reset the PRNG used by sgsn_alloc_ptmsi */
718 srand(1);
719
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100720 ptmsi1 = sgsn_alloc_ptmsi();
721 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
722
723 /* reset the PRNG, so that the same P-TMSI sequence will be generated
724 * again */
725 srand(1);
726
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100727 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
728
729 /* Create a LLE/LLME */
730 OSMO_ASSERT(count(gprs_llme_list()) == 0);
731 lle = gprs_lle_get_or_create(foreign_tlli, 3);
732 OSMO_ASSERT(count(gprs_llme_list()) == 1);
733
734 /* inject the attach request */
735 send_0408_message(lle->llme, foreign_tlli,
736 attach_req, ARRAY_SIZE(attach_req));
737
738 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
739 OSMO_ASSERT(ctx != NULL);
740 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
741
742 /* we expect an identity request (IMEI) */
743 OSMO_ASSERT(sgsn_tx_counter == 1);
744
745 /* inject the identity response (IMEI) */
746 send_0408_message(ctx->llme, foreign_tlli,
747 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
748
749 /* we expect an identity request (IMSI) */
750 OSMO_ASSERT(sgsn_tx_counter == 1);
751
752 /* inject the identity response (IMSI) */
753 send_0408_message(ctx->llme, foreign_tlli,
754 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
755
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100756 /* check that the MM context has not been removed due to a failed
757 * authorization */
758 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
759
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100760 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100761
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100762retry_attach_req:
763
764 if (retry && sgsn_tx_counter == 0) {
765 fprintf(stderr, "Retrying attach request\n");
766 /* re-inject the attach request */
767 send_0408_message(lle->llme, foreign_tlli,
768 attach_req, ARRAY_SIZE(attach_req));
769 }
770
771 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
772 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100773
774 /* inject the auth & ciph response */
775 send_0408_message(ctx->llme, foreign_tlli,
776 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
777
778 /* check that the MM context has not been removed due to a
779 * failed authorization */
780 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
781 }
782
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100783 if (retry && sgsn_tx_counter == 0)
784 goto retry_attach_req;
785
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100786 /* we expect an attach accept/reject */
787 OSMO_ASSERT(sgsn_tx_counter == 1);
788
789 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100790 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100791
792 /* inject the attach complete */
793 send_0408_message(ctx->llme, local_tlli,
794 attach_compl, ARRAY_SIZE(attach_compl));
795
796 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
797
798 /* we don't expect a response */
799 OSMO_ASSERT(sgsn_tx_counter == 0);
800
801 /* inject the detach */
802 send_0408_message(ctx->llme, local_tlli,
803 detach_req, ARRAY_SIZE(detach_req));
804
805 /* verify that things are gone */
806 OSMO_ASSERT(count(gprs_llme_list()) == 0);
807 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
808 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100809}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100810
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100811static void test_gmm_attach_acl(void)
812{
813 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
814
815 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
816 sgsn_acl_add("123456789012345", &sgsn->cfg);
817 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100818 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100819 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100820
821 sgsn->cfg.auth_policy = saved_auth_policy;
822}
823
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100824int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100825 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100826 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100827 if (rc == -ENOTSUP) {
828 OSMO_ASSERT(mmctx->subscr);
829 gprs_subscr_update(mmctx->subscr);
830 }
831 return rc;
832};
833
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100834int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
835 gprs_subscr_update(mmctx->subscr);
836 return 0;
837};
838
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100839static void cleanup_subscr_by_imsi(const char *imsi)
840{
841 struct gsm_subscriber *subscr;
842
843 subscr = gprs_subscr_get_by_imsi(imsi);
844 OSMO_ASSERT(subscr != NULL);
845 gprs_subscr_delete(subscr);
846}
847
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100848static void test_gmm_attach_subscr(void)
849{
850 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
851 struct gsm_subscriber *subscr;
852
853 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100854 subscr_request_update_location_cb = my_subscr_request_update_location;
855 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100856
857 subscr = gprs_subscr_get_or_create("123456789012345");
858 subscr->authorized = 1;
859 subscr_put(subscr);
860
861 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100862 test_gmm_attach(0);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100863
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100864 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100865
866 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100867 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
868 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100869}
870
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100871int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
872{
873 /* Fake an authentication */
874 OSMO_ASSERT(mmctx->subscr);
875 mmctx->is_authenticated = 1;
876 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100877
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100878 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100879};
880
881static void test_gmm_attach_subscr_fake_auth(void)
882{
883 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
884 struct gsm_subscriber *subscr;
885
886 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100887 subscr_request_update_location_cb = my_subscr_request_update_location;
888 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100889
890 subscr = gprs_subscr_get_or_create("123456789012345");
891 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100892 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100893 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100894 subscr_put(subscr);
895
896 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100897 test_gmm_attach(0);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100898
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100899 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100900
901 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100902 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
903 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
904}
905
906int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
907{
908 struct gsm_auth_tuple at = {
909 .sres = {0x51, 0xe5, 0x51, 0xe5},
910 .key_seq = 0
911 };
912
913 /* Fake an authentication */
914 OSMO_ASSERT(mmctx->subscr);
915 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
916
917 gprs_subscr_update_auth_info(mmctx->subscr);
918
919 return 0;
920};
921
922static void test_gmm_attach_subscr_real_auth(void)
923{
924 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
925 struct gsm_subscriber *subscr;
926
927 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
928 subscr_request_update_location_cb = my_subscr_request_update_location;
929 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
930
931 subscr = gprs_subscr_get_or_create("123456789012345");
932 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100933 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100934 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100935 subscr_put(subscr);
936
937 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100938 test_gmm_attach(0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100939
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100940 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100941
942 sgsn->cfg.auth_policy = saved_auth_policy;
943 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
944 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100945}
946
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100947#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
948 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
949
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100950static int auth_info_skip = 0;
951static int upd_loc_skip = 0;
952
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100953int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
954{
955 static const uint8_t send_auth_info_res[] = {
956 0x0a,
957 TEST_GSUP_IMSI_LONG_IE,
958 0x03, 0x22, /* Auth tuple */
959 0x20, 0x10,
960 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
961 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
962 0x21, 0x04,
963 0x51, 0xe5, 0x51, 0xe5,
964 0x22, 0x08,
965 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
966 };
967
968 OSMO_ASSERT(mmctx->subscr);
969
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100970 if (auth_info_skip > 0) {
971 auth_info_skip -= 1;
972 return -EAGAIN;
973 }
974
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100975 /* Fake an SendAuthInfoRes */
976 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
977
978 return 0;
979};
980
981int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
982 static const uint8_t update_location_res[] = {
983 0x06,
984 TEST_GSUP_IMSI_LONG_IE,
985 0x04, 0x00, /* PDP info complete */
986 0x05, 0x12,
987 0x10, 0x01, 0x01,
988 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
989 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
990 };
991
992 OSMO_ASSERT(mmctx->subscr);
993
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100994 if (upd_loc_skip > 0) {
995 upd_loc_skip -= 1;
996 return -EAGAIN;
997 }
998
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100999 /* Fake an UpdateLocRes */
1000 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1001};
1002
1003
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001004static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001005{
1006 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1007 struct gsm_subscriber *subscr;
1008
1009 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1010 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1011 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001012 if (retry) {
1013 upd_loc_skip = 3;
1014 auth_info_skip = 3;
1015 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001016
1017 subscr = gprs_subscr_get_or_create("123456789012345");
1018 subscr->authorized = 1;
1019 sgsn->cfg.require_authentication = 1;
1020 sgsn->cfg.require_update_location = 1;
1021 subscr_put(subscr);
1022
1023 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001024 test_gmm_attach(retry);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001025
1026 subscr = gprs_subscr_get_by_imsi("123456789012345");
1027 OSMO_ASSERT(subscr != NULL);
1028 gprs_subscr_delete(subscr);
1029
1030 sgsn->cfg.auth_policy = saved_auth_policy;
1031 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1032 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001033 upd_loc_skip = 0;
1034 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001035}
1036
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001037/*
1038 * Test the GMM Rejects
1039 */
1040static void test_gmm_reject(void)
1041{
1042 struct gprs_ra_id raid = { 0, };
1043 struct sgsn_mm_ctx *ctx = NULL;
1044 uint32_t foreign_tlli;
1045 struct gprs_llc_lle *lle;
1046 int idx;
1047
1048 /* DTAP - Attach Request */
1049 /* Invalid MI length */
1050 static const unsigned char attach_req_inv_mi_len[] = {
1051 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1052 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1053 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1054 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1055 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1056 };
1057
1058 /* DTAP - Attach Request */
1059 /* Invalid MI type (IMEI) */
1060 static const unsigned char attach_req_inv_mi_type[] = {
1061 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1062 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1063 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1064 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1065 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1066 };
1067
1068 /* DTAP - Routing Area Update Request */
1069 static const unsigned char dtap_ra_upd_req[] = {
1070 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1071 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1072 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1073 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1074 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1075 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1076 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1077 };
1078
1079 /* DTAP - Routing Area Update Request */
1080 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1081 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1082 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1083 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1084 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1085 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1086 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1087 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1088 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1089 };
1090
1091 /* DTAP - Routing Area Update Request */
1092 /* Invalid cap length */
1093 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1094 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1095 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1096 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1097 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1098 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1099 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1100 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1101 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1102 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1103 };
1104
1105 struct test {
1106 const char *title;
1107 const unsigned char *msg;
1108 unsigned msg_len;
1109 unsigned num_resp;
1110
1111 };
1112 static struct test tests[] = {
1113 {
1114 .title = "Attach Request (invalid MI length)",
1115 .msg = attach_req_inv_mi_len,
1116 .msg_len = sizeof(attach_req_inv_mi_len),
1117 .num_resp = 1 /* Reject */
1118
1119 },
1120 {
1121 .title = "Attach Request (invalid MI type)",
1122 .msg = attach_req_inv_mi_type,
1123 .msg_len = sizeof(attach_req_inv_mi_type),
1124 .num_resp = 1 /* Reject */
1125 },
1126 {
1127 .title = "Routing Area Update Request (valid)",
1128 .msg = dtap_ra_upd_req,
1129 .msg_len = sizeof(dtap_ra_upd_req),
1130 .num_resp = 2 /* XID Reset + Reject */
1131 },
1132 {
1133 .title = "Routing Area Update Request (invalid type)",
1134 .msg = dtap_ra_upd_req_inv_type,
1135 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1136 .num_resp = 1 /* Reject */
1137 },
1138 {
1139 .title = "Routing Area Update Request (invalid CAP length)",
1140 .msg = dtap_ra_upd_req_inv_cap_len,
1141 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1142 .num_resp = 1 /* Reject */
1143 },
1144 };
1145
1146 printf("Testing GMM reject\n");
1147
1148 /* reset the PRNG used by sgsn_alloc_ptmsi */
1149 srand(1);
1150
1151 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1152
1153 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1154
1155 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1156 const struct test *test = &tests[idx];
1157 printf(" - %s\n", test->title);
1158
1159 /* Create a LLE/LLME */
1160 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1161 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1162
1163 /* Inject the Request message */
1164 send_0408_message(lle->llme, foreign_tlli,
1165 test->msg, test->msg_len);
1166
1167 /* We expect a Reject message */
1168 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1169 sgsn_tx_counter, test->num_resp);
1170 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1171
1172 /* verify that LLME/MM are removed */
1173 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1174 OSMO_ASSERT(ctx == NULL);
1175 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1176 }
1177}
1178
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001179/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001180 * Test cancellation of attached MM contexts
1181 */
1182static void test_gmm_cancel(void)
1183{
1184 struct gprs_ra_id raid = { 0, };
1185 struct sgsn_mm_ctx *ctx = NULL;
1186 struct sgsn_mm_ctx *ictx;
1187 uint32_t ptmsi1;
1188 uint32_t foreign_tlli;
1189 uint32_t local_tlli = 0;
1190 struct gprs_llc_lle *lle;
1191 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1192
1193 /* DTAP - Attach Request */
1194 /* The P-TMSI is not known by the SGSN */
1195 static const unsigned char attach_req[] = {
1196 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1197 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1198 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1199 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1200 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1201 };
1202
1203 /* DTAP - Identity Response IMEI */
1204 static const unsigned char ident_resp_imei[] = {
1205 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1206 0x56
1207 };
1208
1209 /* DTAP - Identity Response IMSI */
1210 static const unsigned char ident_resp_imsi[] = {
1211 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1212 0x54
1213 };
1214
1215 /* DTAP - Attach Complete */
1216 static const unsigned char attach_compl[] = {
1217 0x08, 0x03
1218 };
1219
1220 printf("Testing cancellation\n");
1221
1222 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1223
1224 /* reset the PRNG used by sgsn_alloc_ptmsi */
1225 srand(1);
1226
1227 ptmsi1 = sgsn_alloc_ptmsi();
1228 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1229
1230 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1231 * again */
1232 srand(1);
1233
1234 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1235
1236 /* Create a LLE/LLME */
1237 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1238 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1239 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1240
1241 /* inject the attach request */
1242 send_0408_message(lle->llme, foreign_tlli,
1243 attach_req, ARRAY_SIZE(attach_req));
1244
1245 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1246 OSMO_ASSERT(ctx != NULL);
1247 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1248
1249 /* we expect an identity request (IMEI) */
1250 OSMO_ASSERT(sgsn_tx_counter == 1);
1251
1252 /* inject the identity response (IMEI) */
1253 send_0408_message(ctx->llme, foreign_tlli,
1254 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1255
1256 /* we expect an identity request (IMSI) */
1257 OSMO_ASSERT(sgsn_tx_counter == 1);
1258
1259 /* inject the identity response (IMSI) */
1260 send_0408_message(ctx->llme, foreign_tlli,
1261 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1262
1263 /* check that the MM context has not been removed due to a failed
1264 * authorization */
1265 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1266
1267 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1268
1269 /* we expect an attach accept/reject */
1270 OSMO_ASSERT(sgsn_tx_counter == 1);
1271
1272 /* this has been randomly assigned by the SGSN */
1273 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1274
1275 /* inject the attach complete */
1276 send_0408_message(ctx->llme, local_tlli,
1277 attach_compl, ARRAY_SIZE(attach_compl));
1278
1279 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1280
1281 /* we don't expect a response */
1282 OSMO_ASSERT(sgsn_tx_counter == 0);
1283
1284 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001285 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001286
1287 /* verify that things are gone */
1288 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1289 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1290 OSMO_ASSERT(!ictx);
1291
1292 sgsn->cfg.auth_policy = saved_auth_policy;
1293}
1294
1295/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001296 * Test the dynamic allocation of P-TMSIs
1297 */
1298static void test_gmm_ptmsi_allocation(void)
1299{
1300 struct gprs_ra_id raid = { 0, };
1301 struct sgsn_mm_ctx *ctx = NULL;
1302 struct sgsn_mm_ctx *ictx;
1303 uint32_t foreign_tlli;
1304 uint32_t ptmsi1;
1305 uint32_t ptmsi2;
1306 uint32_t old_ptmsi;
1307 uint32_t local_tlli = 0;
1308 struct gprs_llc_lle *lle;
1309 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1310
1311 /* DTAP - Attach Request (IMSI 12131415161718) */
1312 static const unsigned char attach_req[] = {
1313 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1314 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1315 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1316 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1317 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1318 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1319 0x00,
1320 };
1321
1322 /* DTAP - Identity Response IMEI */
1323 static const unsigned char ident_resp_imei[] = {
1324 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1325 0x56
1326 };
1327
1328 /* DTAP - Attach Complete */
1329 static const unsigned char attach_compl[] = {
1330 0x08, 0x03
1331 };
1332
1333 /* DTAP - Routing Area Update Request */
1334 static const unsigned char ra_upd_req[] = {
1335 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1336 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1337 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1338 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1339 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1340 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1341 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1342 };
1343
1344 /* DTAP - Routing Area Update Complete */
1345 static const unsigned char ra_upd_complete[] = {
1346 0x08, 0x0a
1347 };
1348
1349 /* DTAP - Detach Request (MO) */
1350 /* normal detach, power_off = 1 */
1351 static const unsigned char detach_req[] = {
1352 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1353 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1354 };
1355
1356 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1357
1358 printf("Testing P-TMSI allocation\n");
1359
1360 printf(" - sgsn_alloc_ptmsi\n");
1361
1362 /* reset the PRNG used by sgsn_alloc_ptmsi */
1363 srand(1);
1364
1365 ptmsi1 = sgsn_alloc_ptmsi();
1366 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1367
1368 ptmsi2 = sgsn_alloc_ptmsi();
1369 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1370
1371 OSMO_ASSERT(ptmsi1 != ptmsi2);
1372
1373 printf(" - Repeated Attach Request\n");
1374
1375 /* reset the PRNG, so that the same P-TMSI will be generated
1376 * again */
1377 srand(1);
1378
1379 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1380
1381 /* Create a LLE/LLME */
1382 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1383 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1384 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1385
1386 /* inject the attach request */
1387 send_0408_message(lle->llme, foreign_tlli,
1388 attach_req, ARRAY_SIZE(attach_req));
1389
1390 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1391 OSMO_ASSERT(ctx != NULL);
1392 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1393 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1394
1395 old_ptmsi = ctx->p_tmsi_old;
1396
1397 /* we expect an identity request (IMEI) */
1398 OSMO_ASSERT(sgsn_tx_counter == 1);
1399
1400 /* inject the identity response (IMEI) */
1401 send_0408_message(ctx->llme, foreign_tlli,
1402 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1403
1404 /* check that the MM context has not been removed due to a failed
1405 * authorization */
1406 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1407
1408 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1409 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1410
1411 /* we expect an attach accept */
1412 OSMO_ASSERT(sgsn_tx_counter == 1);
1413
1414 /* we ignore this and send the attach again */
1415 send_0408_message(lle->llme, foreign_tlli,
1416 attach_req, ARRAY_SIZE(attach_req));
1417
1418 /* the allocated P-TMSI should be the same */
1419 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1420 OSMO_ASSERT(ctx != NULL);
1421 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1422 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1423 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1424
1425 /* inject the attach complete */
1426 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1427 send_0408_message(ctx->llme, local_tlli,
1428 attach_compl, ARRAY_SIZE(attach_compl));
1429
1430 /* we don't expect a response */
1431 OSMO_ASSERT(sgsn_tx_counter == 0);
1432
1433 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1434 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1435 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1436
1437 printf(" - Repeated RA Update Request\n");
1438
1439 /* inject the RA update request */
1440 send_0408_message(ctx->llme, local_tlli,
1441 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1442
1443 /* we expect an RA update accept */
1444 OSMO_ASSERT(sgsn_tx_counter == 1);
1445
1446 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1447 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1448 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1449
1450 /* repeat the RA update request */
1451 send_0408_message(ctx->llme, local_tlli,
1452 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1453
1454 /* we expect an RA update accept */
1455 OSMO_ASSERT(sgsn_tx_counter == 1);
1456
1457 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1458 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1459 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1460
1461 /* inject the RA update complete */
1462 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1463 send_0408_message(ctx->llme, local_tlli,
1464 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1465
1466 /* we don't expect a response */
1467 OSMO_ASSERT(sgsn_tx_counter == 0);
1468
1469 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1470 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1471 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1472
1473 /* inject the detach */
1474 send_0408_message(ctx->llme, local_tlli,
1475 detach_req, ARRAY_SIZE(detach_req));
1476
1477 /* verify that things are gone */
1478 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1479 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1480 OSMO_ASSERT(!ictx);
1481
1482 sgsn->cfg.auth_policy = saved_auth_policy;
1483}
1484
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001485static struct log_info_cat gprs_categories[] = {
1486 [DMM] = {
1487 .name = "DMM",
1488 .description = "Layer3 Mobility Management (MM)",
1489 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001490 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001491 },
1492 [DPAG] = {
1493 .name = "DPAG",
1494 .description = "Paging Subsystem",
1495 .color = "\033[1;38m",
1496 .enabled = 1, .loglevel = LOGL_NOTICE,
1497 },
1498 [DMEAS] = {
1499 .name = "DMEAS",
1500 .description = "Radio Measurement Processing",
1501 .enabled = 0, .loglevel = LOGL_NOTICE,
1502 },
1503 [DREF] = {
1504 .name = "DREF",
1505 .description = "Reference Counting",
1506 .enabled = 0, .loglevel = LOGL_NOTICE,
1507 },
1508 [DGPRS] = {
1509 .name = "DGPRS",
1510 .description = "GPRS Packet Service",
1511 .enabled = 1, .loglevel = LOGL_DEBUG,
1512 },
1513 [DNS] = {
1514 .name = "DNS",
1515 .description = "GPRS Network Service (NS)",
1516 .enabled = 1, .loglevel = LOGL_INFO,
1517 },
1518 [DBSSGP] = {
1519 .name = "DBSSGP",
1520 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1521 .enabled = 1, .loglevel = LOGL_DEBUG,
1522 },
1523 [DLLC] = {
1524 .name = "DLLC",
1525 .description = "GPRS Logical Link Control Protocol (LLC)",
1526 .enabled = 1, .loglevel = LOGL_DEBUG,
1527 },
1528 [DSNDCP] = {
1529 .name = "DSNDCP",
1530 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1531 .enabled = 1, .loglevel = LOGL_DEBUG,
1532 },
1533};
1534
1535static struct log_info info = {
1536 .cat = gprs_categories,
1537 .num_cat = ARRAY_SIZE(gprs_categories),
1538};
1539
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001540int main(int argc, char **argv)
1541{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001542 osmo_init_logging(&info);
1543 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1544 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1545
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001546 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001547 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001548
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001549 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001550 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001551 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001552 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001553 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001554 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001555 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001556 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001557 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001558 test_gmm_attach_acl();
1559 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001560 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001561 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001562 test_gmm_attach_subscr_gsup_auth(0);
1563 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001564 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001565 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001566 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001567 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001568
1569 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01001570 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001571 return 0;
1572}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001573
1574
1575/* stubs */
1576struct osmo_prim_hdr;
1577int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1578{
1579 abort();
1580}