blob: 6980a9015a6d38199f98960ba1d530b9b5555e39 [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 Erlbeckbe2c8d92014-11-12 10:18:09 +0100839static void test_gmm_attach_subscr(void)
840{
841 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
842 struct gsm_subscriber *subscr;
843
844 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100845 subscr_request_update_location_cb = my_subscr_request_update_location;
846 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100847
848 subscr = gprs_subscr_get_or_create("123456789012345");
849 subscr->authorized = 1;
850 subscr_put(subscr);
851
852 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100853 test_gmm_attach(0);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100854
855 subscr = gprs_subscr_get_by_imsi("123456789012345");
856 OSMO_ASSERT(subscr != NULL);
857 gprs_subscr_delete(subscr);
858
859 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100860 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
861 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100862}
863
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100864int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
865{
866 /* Fake an authentication */
867 OSMO_ASSERT(mmctx->subscr);
868 mmctx->is_authenticated = 1;
869 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100870
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100871 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100872};
873
874static void test_gmm_attach_subscr_fake_auth(void)
875{
876 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
877 struct gsm_subscriber *subscr;
878
879 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100880 subscr_request_update_location_cb = my_subscr_request_update_location;
881 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100882
883 subscr = gprs_subscr_get_or_create("123456789012345");
884 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100885 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100886 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100887 subscr_put(subscr);
888
889 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100890 test_gmm_attach(0);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100891
892 subscr = gprs_subscr_get_by_imsi("123456789012345");
893 OSMO_ASSERT(subscr != NULL);
894 gprs_subscr_delete(subscr);
895
896 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100897 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
898 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
899}
900
901int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
902{
903 struct gsm_auth_tuple at = {
904 .sres = {0x51, 0xe5, 0x51, 0xe5},
905 .key_seq = 0
906 };
907
908 /* Fake an authentication */
909 OSMO_ASSERT(mmctx->subscr);
910 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
911
912 gprs_subscr_update_auth_info(mmctx->subscr);
913
914 return 0;
915};
916
917static void test_gmm_attach_subscr_real_auth(void)
918{
919 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
920 struct gsm_subscriber *subscr;
921
922 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
923 subscr_request_update_location_cb = my_subscr_request_update_location;
924 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
925
926 subscr = gprs_subscr_get_or_create("123456789012345");
927 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100928 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100929 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100930 subscr_put(subscr);
931
932 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100933 test_gmm_attach(0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100934
935 subscr = gprs_subscr_get_by_imsi("123456789012345");
936 OSMO_ASSERT(subscr != NULL);
937 gprs_subscr_delete(subscr);
938
939 sgsn->cfg.auth_policy = saved_auth_policy;
940 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
941 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100942}
943
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100944#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
945 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
946
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100947static int auth_info_skip = 0;
948static int upd_loc_skip = 0;
949
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100950int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
951{
952 static const uint8_t send_auth_info_res[] = {
953 0x0a,
954 TEST_GSUP_IMSI_LONG_IE,
955 0x03, 0x22, /* Auth tuple */
956 0x20, 0x10,
957 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
958 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
959 0x21, 0x04,
960 0x51, 0xe5, 0x51, 0xe5,
961 0x22, 0x08,
962 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
963 };
964
965 OSMO_ASSERT(mmctx->subscr);
966
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100967 if (auth_info_skip > 0) {
968 auth_info_skip -= 1;
969 return -EAGAIN;
970 }
971
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100972 /* Fake an SendAuthInfoRes */
973 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
974
975 return 0;
976};
977
978int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
979 static const uint8_t update_location_res[] = {
980 0x06,
981 TEST_GSUP_IMSI_LONG_IE,
982 0x04, 0x00, /* PDP info complete */
983 0x05, 0x12,
984 0x10, 0x01, 0x01,
985 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
986 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
987 };
988
989 OSMO_ASSERT(mmctx->subscr);
990
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100991 if (upd_loc_skip > 0) {
992 upd_loc_skip -= 1;
993 return -EAGAIN;
994 }
995
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100996 /* Fake an UpdateLocRes */
997 return rx_gsup_message(update_location_res, sizeof(update_location_res));
998};
999
1000
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001001static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001002{
1003 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1004 struct gsm_subscriber *subscr;
1005
1006 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1007 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1008 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001009 if (retry) {
1010 upd_loc_skip = 3;
1011 auth_info_skip = 3;
1012 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001013
1014 subscr = gprs_subscr_get_or_create("123456789012345");
1015 subscr->authorized = 1;
1016 sgsn->cfg.require_authentication = 1;
1017 sgsn->cfg.require_update_location = 1;
1018 subscr_put(subscr);
1019
1020 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001021 test_gmm_attach(retry);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001022
1023 subscr = gprs_subscr_get_by_imsi("123456789012345");
1024 OSMO_ASSERT(subscr != NULL);
1025 gprs_subscr_delete(subscr);
1026
1027 sgsn->cfg.auth_policy = saved_auth_policy;
1028 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1029 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001030 upd_loc_skip = 0;
1031 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001032}
1033
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001034/*
1035 * Test the GMM Rejects
1036 */
1037static void test_gmm_reject(void)
1038{
1039 struct gprs_ra_id raid = { 0, };
1040 struct sgsn_mm_ctx *ctx = NULL;
1041 uint32_t foreign_tlli;
1042 struct gprs_llc_lle *lle;
1043 int idx;
1044
1045 /* DTAP - Attach Request */
1046 /* Invalid MI length */
1047 static const unsigned char attach_req_inv_mi_len[] = {
1048 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1049 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1050 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1051 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1052 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1053 };
1054
1055 /* DTAP - Attach Request */
1056 /* Invalid MI type (IMEI) */
1057 static const unsigned char attach_req_inv_mi_type[] = {
1058 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1059 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1060 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1061 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1062 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1063 };
1064
1065 /* DTAP - Routing Area Update Request */
1066 static const unsigned char dtap_ra_upd_req[] = {
1067 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1068 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1069 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1070 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1071 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1072 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1073 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1074 };
1075
1076 /* DTAP - Routing Area Update Request */
1077 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1078 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1079 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1080 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1081 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1082 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1083 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1084 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1085 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1086 };
1087
1088 /* DTAP - Routing Area Update Request */
1089 /* Invalid cap length */
1090 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1091 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1092 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1093 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1094 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1095 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1096 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1097 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1098 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1099 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1100 };
1101
1102 struct test {
1103 const char *title;
1104 const unsigned char *msg;
1105 unsigned msg_len;
1106 unsigned num_resp;
1107
1108 };
1109 static struct test tests[] = {
1110 {
1111 .title = "Attach Request (invalid MI length)",
1112 .msg = attach_req_inv_mi_len,
1113 .msg_len = sizeof(attach_req_inv_mi_len),
1114 .num_resp = 1 /* Reject */
1115
1116 },
1117 {
1118 .title = "Attach Request (invalid MI type)",
1119 .msg = attach_req_inv_mi_type,
1120 .msg_len = sizeof(attach_req_inv_mi_type),
1121 .num_resp = 1 /* Reject */
1122 },
1123 {
1124 .title = "Routing Area Update Request (valid)",
1125 .msg = dtap_ra_upd_req,
1126 .msg_len = sizeof(dtap_ra_upd_req),
1127 .num_resp = 2 /* XID Reset + Reject */
1128 },
1129 {
1130 .title = "Routing Area Update Request (invalid type)",
1131 .msg = dtap_ra_upd_req_inv_type,
1132 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1133 .num_resp = 1 /* Reject */
1134 },
1135 {
1136 .title = "Routing Area Update Request (invalid CAP length)",
1137 .msg = dtap_ra_upd_req_inv_cap_len,
1138 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1139 .num_resp = 1 /* Reject */
1140 },
1141 };
1142
1143 printf("Testing GMM reject\n");
1144
1145 /* reset the PRNG used by sgsn_alloc_ptmsi */
1146 srand(1);
1147
1148 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1149
1150 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1151
1152 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1153 const struct test *test = &tests[idx];
1154 printf(" - %s\n", test->title);
1155
1156 /* Create a LLE/LLME */
1157 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1158 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1159
1160 /* Inject the Request message */
1161 send_0408_message(lle->llme, foreign_tlli,
1162 test->msg, test->msg_len);
1163
1164 /* We expect a Reject message */
1165 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1166 sgsn_tx_counter, test->num_resp);
1167 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1168
1169 /* verify that LLME/MM are removed */
1170 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1171 OSMO_ASSERT(ctx == NULL);
1172 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1173 }
1174}
1175
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001176/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001177 * Test cancellation of attached MM contexts
1178 */
1179static void test_gmm_cancel(void)
1180{
1181 struct gprs_ra_id raid = { 0, };
1182 struct sgsn_mm_ctx *ctx = NULL;
1183 struct sgsn_mm_ctx *ictx;
1184 uint32_t ptmsi1;
1185 uint32_t foreign_tlli;
1186 uint32_t local_tlli = 0;
1187 struct gprs_llc_lle *lle;
1188 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1189
1190 /* DTAP - Attach Request */
1191 /* The P-TMSI is not known by the SGSN */
1192 static const unsigned char attach_req[] = {
1193 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1194 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1195 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1196 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1197 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1198 };
1199
1200 /* DTAP - Identity Response IMEI */
1201 static const unsigned char ident_resp_imei[] = {
1202 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1203 0x56
1204 };
1205
1206 /* DTAP - Identity Response IMSI */
1207 static const unsigned char ident_resp_imsi[] = {
1208 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1209 0x54
1210 };
1211
1212 /* DTAP - Attach Complete */
1213 static const unsigned char attach_compl[] = {
1214 0x08, 0x03
1215 };
1216
1217 printf("Testing cancellation\n");
1218
1219 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1220
1221 /* reset the PRNG used by sgsn_alloc_ptmsi */
1222 srand(1);
1223
1224 ptmsi1 = sgsn_alloc_ptmsi();
1225 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1226
1227 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1228 * again */
1229 srand(1);
1230
1231 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1232
1233 /* Create a LLE/LLME */
1234 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1235 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1236 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1237
1238 /* inject the attach request */
1239 send_0408_message(lle->llme, foreign_tlli,
1240 attach_req, ARRAY_SIZE(attach_req));
1241
1242 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1243 OSMO_ASSERT(ctx != NULL);
1244 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1245
1246 /* we expect an identity request (IMEI) */
1247 OSMO_ASSERT(sgsn_tx_counter == 1);
1248
1249 /* inject the identity response (IMEI) */
1250 send_0408_message(ctx->llme, foreign_tlli,
1251 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1252
1253 /* we expect an identity request (IMSI) */
1254 OSMO_ASSERT(sgsn_tx_counter == 1);
1255
1256 /* inject the identity response (IMSI) */
1257 send_0408_message(ctx->llme, foreign_tlli,
1258 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1259
1260 /* check that the MM context has not been removed due to a failed
1261 * authorization */
1262 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1263
1264 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1265
1266 /* we expect an attach accept/reject */
1267 OSMO_ASSERT(sgsn_tx_counter == 1);
1268
1269 /* this has been randomly assigned by the SGSN */
1270 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1271
1272 /* inject the attach complete */
1273 send_0408_message(ctx->llme, local_tlli,
1274 attach_compl, ARRAY_SIZE(attach_compl));
1275
1276 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1277
1278 /* we don't expect a response */
1279 OSMO_ASSERT(sgsn_tx_counter == 0);
1280
1281 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001282 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001283
1284 /* verify that things are gone */
1285 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1286 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1287 OSMO_ASSERT(!ictx);
1288
1289 sgsn->cfg.auth_policy = saved_auth_policy;
1290}
1291
1292/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001293 * Test the dynamic allocation of P-TMSIs
1294 */
1295static void test_gmm_ptmsi_allocation(void)
1296{
1297 struct gprs_ra_id raid = { 0, };
1298 struct sgsn_mm_ctx *ctx = NULL;
1299 struct sgsn_mm_ctx *ictx;
1300 uint32_t foreign_tlli;
1301 uint32_t ptmsi1;
1302 uint32_t ptmsi2;
1303 uint32_t old_ptmsi;
1304 uint32_t local_tlli = 0;
1305 struct gprs_llc_lle *lle;
1306 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1307
1308 /* DTAP - Attach Request (IMSI 12131415161718) */
1309 static const unsigned char attach_req[] = {
1310 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1311 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1312 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1313 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1314 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1315 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1316 0x00,
1317 };
1318
1319 /* DTAP - Identity Response IMEI */
1320 static const unsigned char ident_resp_imei[] = {
1321 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1322 0x56
1323 };
1324
1325 /* DTAP - Attach Complete */
1326 static const unsigned char attach_compl[] = {
1327 0x08, 0x03
1328 };
1329
1330 /* DTAP - Routing Area Update Request */
1331 static const unsigned char ra_upd_req[] = {
1332 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1333 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1334 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1335 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1336 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1337 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1338 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1339 };
1340
1341 /* DTAP - Routing Area Update Complete */
1342 static const unsigned char ra_upd_complete[] = {
1343 0x08, 0x0a
1344 };
1345
1346 /* DTAP - Detach Request (MO) */
1347 /* normal detach, power_off = 1 */
1348 static const unsigned char detach_req[] = {
1349 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1350 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1351 };
1352
1353 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1354
1355 printf("Testing P-TMSI allocation\n");
1356
1357 printf(" - sgsn_alloc_ptmsi\n");
1358
1359 /* reset the PRNG used by sgsn_alloc_ptmsi */
1360 srand(1);
1361
1362 ptmsi1 = sgsn_alloc_ptmsi();
1363 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1364
1365 ptmsi2 = sgsn_alloc_ptmsi();
1366 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1367
1368 OSMO_ASSERT(ptmsi1 != ptmsi2);
1369
1370 printf(" - Repeated Attach Request\n");
1371
1372 /* reset the PRNG, so that the same P-TMSI will be generated
1373 * again */
1374 srand(1);
1375
1376 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1377
1378 /* Create a LLE/LLME */
1379 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1380 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1381 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1382
1383 /* inject the attach request */
1384 send_0408_message(lle->llme, foreign_tlli,
1385 attach_req, ARRAY_SIZE(attach_req));
1386
1387 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1388 OSMO_ASSERT(ctx != NULL);
1389 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1390 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1391
1392 old_ptmsi = ctx->p_tmsi_old;
1393
1394 /* we expect an identity request (IMEI) */
1395 OSMO_ASSERT(sgsn_tx_counter == 1);
1396
1397 /* inject the identity response (IMEI) */
1398 send_0408_message(ctx->llme, foreign_tlli,
1399 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1400
1401 /* check that the MM context has not been removed due to a failed
1402 * authorization */
1403 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1404
1405 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1406 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1407
1408 /* we expect an attach accept */
1409 OSMO_ASSERT(sgsn_tx_counter == 1);
1410
1411 /* we ignore this and send the attach again */
1412 send_0408_message(lle->llme, foreign_tlli,
1413 attach_req, ARRAY_SIZE(attach_req));
1414
1415 /* the allocated P-TMSI should be the same */
1416 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1417 OSMO_ASSERT(ctx != NULL);
1418 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1419 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1420 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1421
1422 /* inject the attach complete */
1423 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1424 send_0408_message(ctx->llme, local_tlli,
1425 attach_compl, ARRAY_SIZE(attach_compl));
1426
1427 /* we don't expect a response */
1428 OSMO_ASSERT(sgsn_tx_counter == 0);
1429
1430 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1431 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1432 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1433
1434 printf(" - Repeated RA Update Request\n");
1435
1436 /* inject the RA update request */
1437 send_0408_message(ctx->llme, local_tlli,
1438 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1439
1440 /* we expect an RA update accept */
1441 OSMO_ASSERT(sgsn_tx_counter == 1);
1442
1443 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1444 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1445 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1446
1447 /* repeat the RA update request */
1448 send_0408_message(ctx->llme, local_tlli,
1449 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1450
1451 /* we expect an RA update accept */
1452 OSMO_ASSERT(sgsn_tx_counter == 1);
1453
1454 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1455 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1456 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1457
1458 /* inject the RA update complete */
1459 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1460 send_0408_message(ctx->llme, local_tlli,
1461 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1462
1463 /* we don't expect a response */
1464 OSMO_ASSERT(sgsn_tx_counter == 0);
1465
1466 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1467 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1468 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1469
1470 /* inject the detach */
1471 send_0408_message(ctx->llme, local_tlli,
1472 detach_req, ARRAY_SIZE(detach_req));
1473
1474 /* verify that things are gone */
1475 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1476 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1477 OSMO_ASSERT(!ictx);
1478
1479 sgsn->cfg.auth_policy = saved_auth_policy;
1480}
1481
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001482static struct log_info_cat gprs_categories[] = {
1483 [DMM] = {
1484 .name = "DMM",
1485 .description = "Layer3 Mobility Management (MM)",
1486 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001487 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001488 },
1489 [DPAG] = {
1490 .name = "DPAG",
1491 .description = "Paging Subsystem",
1492 .color = "\033[1;38m",
1493 .enabled = 1, .loglevel = LOGL_NOTICE,
1494 },
1495 [DMEAS] = {
1496 .name = "DMEAS",
1497 .description = "Radio Measurement Processing",
1498 .enabled = 0, .loglevel = LOGL_NOTICE,
1499 },
1500 [DREF] = {
1501 .name = "DREF",
1502 .description = "Reference Counting",
1503 .enabled = 0, .loglevel = LOGL_NOTICE,
1504 },
1505 [DGPRS] = {
1506 .name = "DGPRS",
1507 .description = "GPRS Packet Service",
1508 .enabled = 1, .loglevel = LOGL_DEBUG,
1509 },
1510 [DNS] = {
1511 .name = "DNS",
1512 .description = "GPRS Network Service (NS)",
1513 .enabled = 1, .loglevel = LOGL_INFO,
1514 },
1515 [DBSSGP] = {
1516 .name = "DBSSGP",
1517 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1518 .enabled = 1, .loglevel = LOGL_DEBUG,
1519 },
1520 [DLLC] = {
1521 .name = "DLLC",
1522 .description = "GPRS Logical Link Control Protocol (LLC)",
1523 .enabled = 1, .loglevel = LOGL_DEBUG,
1524 },
1525 [DSNDCP] = {
1526 .name = "DSNDCP",
1527 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1528 .enabled = 1, .loglevel = LOGL_DEBUG,
1529 },
1530};
1531
1532static struct log_info info = {
1533 .cat = gprs_categories,
1534 .num_cat = ARRAY_SIZE(gprs_categories),
1535};
1536
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001537int main(int argc, char **argv)
1538{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001539 osmo_init_logging(&info);
1540 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1541 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1542
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001543 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001544 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001545
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001546 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001547 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001548 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001549 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001550 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001551 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001552 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001553 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001554 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001555 test_gmm_attach_acl();
1556 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001557 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001558 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001559 test_gmm_attach_subscr_gsup_auth(0);
1560 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001561 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001562 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001563 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001564 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001565
1566 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01001567 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001568 return 0;
1569}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001570
1571
1572/* stubs */
1573struct osmo_prim_hdr;
1574int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1575{
1576 abort();
1577}