blob: adaa32804699cb33cf330b5a6033c3254cd14ba1 [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,
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +010047 .subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020048 },
49};
50struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010051unsigned sgsn_tx_counter = 0;
52
53/* override */
54int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
55 struct bssgp_dl_ud_par *dup)
56{
57 sgsn_tx_counter += 1;
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +010058 msgb_free(msg);
Jacob Erlbeck189999d2014-10-27 14:34:13 +010059 return 0;
60}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020061
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010062/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
63void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *, struct gsm_subscriber *);
64void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *, struct gsm_subscriber *) =
65 &__real_sgsn_update_subscriber_data;
66
67void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
68 struct gsm_subscriber *subscr)
69{
70 (*update_subscriber_data_cb)(mmctx, subscr);
71}
72
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010073/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
74int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
75int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
76 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010077
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010078int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
79 return (*subscr_request_update_location_cb)(mmctx);
80};
81
82/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
83int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
84int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
85 &__real_gprs_subscr_request_auth_info;
86
87int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
88 return (*subscr_request_auth_info_cb)(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010089};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010090
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020091static int count(struct llist_head *head)
92{
93 struct llist_head *cur;
94 int count = 0;
95
96 llist_for_each(cur, head)
97 count += 1;
98
99 return count;
100}
101
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200102static struct msgb *create_msg(const uint8_t *data, size_t len)
103{
104 struct msgb *msg = msgb_alloc(len + 8, "test message");
105 msg->l1h = msgb_put(msg, 8);
106 msg->l2h = msgb_put(msg, len);
107 memcpy(msg->l2h, data, len);
108
109 msgb_bcid(msg) = msg->l1h;
110 msgb_gmmh(msg) = msg->l2h;
111 return msg;
112}
113
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100114/*
115 * Create a context and search for it
116 */
117static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
118{
119 struct sgsn_mm_ctx *ctx, *ictx;
120 struct gprs_llc_lle *lle;
121 int old_count = count(gprs_llme_list());
122
123 lle = gprs_lle_get_or_create(tlli, 3);
124 ctx = sgsn_mm_ctx_alloc(tlli, raid);
125 ctx->mm_state = GMM_REGISTERED_NORMAL;
126 ctx->llme = lle->llme;
127
128 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
129 OSMO_ASSERT(ictx == ctx);
130
131 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
132
133 return ctx;
134}
135
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100136static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
137 const uint8_t *data, size_t data_len)
138{
139 struct msgb *msg;
140
141 sgsn_tx_counter = 0;
142
143 msg = create_msg(data, data_len);
144 msgb_tlli(msg) = tlli;
145 gsm0408_gprs_rcvmsg(msg, llme);
146 msgb_free(msg);
147}
148
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200149static void test_llme(void)
150{
151 struct gprs_llc_lle *lle, *lle_copy;
152 uint32_t local_tlli;
153 uint32_t foreign_tlli;
154
155 printf("Testing LLME allocations\n");
156 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
157 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
158
159 /* initial state */
160 OSMO_ASSERT(count(gprs_llme_list()) == 0);
161
162 /* Create a new entry */
163 lle = gprs_lle_get_or_create(local_tlli, 3);
164 OSMO_ASSERT(lle);
165 OSMO_ASSERT(count(gprs_llme_list()) == 1);
166
167 /* No new entry is created */
168 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
169 OSMO_ASSERT(lle == lle_copy);
170 OSMO_ASSERT(count(gprs_llme_list()) == 1);
171 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
172 OSMO_ASSERT(lle == lle_copy);
173 OSMO_ASSERT(count(gprs_llme_list()) == 1);
174
175 /* unassign which should delete it*/
176 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
177
178 /* Check that everything was cleaned up */
179 OSMO_ASSERT(count(gprs_llme_list()) == 0);
180}
181
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100182struct gsm_subscriber *last_updated_subscr = NULL;
183void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
184 struct gsm_subscriber *subscr)
185{
186 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
187 __func__, mmctx, subscr);
188 last_updated_subscr = subscr;
189}
190
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100191static void assert_subscr(const struct gsm_subscriber *subscr, const char *imsi)
192{
193 struct gsm_subscriber *sfound;
194
195 sfound = gprs_subscr_get_by_imsi(imsi);
196 OSMO_ASSERT(sfound == subscr);
197 subscr_put(sfound);
198
199 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
200}
201
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100202static void test_subscriber(void)
203{
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100204 struct gsm_subscriber *s1, *s2, *s3, *sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100205 const char *imsi1 = "1234567890";
206 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100207 const char *imsi3 = "5656565656";
208 int saved_expiry_timeout = sgsn->cfg.subscriber_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100209
210 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
211
212 printf("Testing core subscriber data API\n");
213
214 /* Check for emptiness */
215 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
216 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100217 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100218
219 /* Allocate entry 1 */
220 s1 = gprs_subscr_get_or_create(imsi1);
221 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100222 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100223 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100224
225 /* Allocate entry 2 */
226 s2 = gprs_subscr_get_or_create(imsi2);
227 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100228
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100229 /* Allocate entry 3 */
230 s3 = gprs_subscr_get_or_create(imsi3);
231
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100232 /* Check entries */
233 assert_subscr(s1, imsi1);
234 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100235 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100236
237 /* Update entry 1 */
238 last_updated_subscr = NULL;
239 gprs_subscr_update(s1);
240 OSMO_ASSERT(last_updated_subscr == s1);
241
242 /* Because of the update, it won't be freed on delete now */
243 gprs_subscr_delete(s1);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100244 sfound = gprs_subscr_get_by_imsi(imsi1);
245 OSMO_ASSERT(sfound != NULL);
246 s1 = sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100247
248 /* Cancel it, so that delete will free it.
249 * Refcount it to make sure s1 won't be freed here */
250 last_updated_subscr = NULL;
251 gprs_subscr_put_and_cancel(subscr_get(s1));
252 OSMO_ASSERT(last_updated_subscr == s1);
253
254 /* Cancelled entries are still being found */
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100255 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100256
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100257 /* Free entry 1 (GPRS_SUBSCRIBER_CANCELLED is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100258 gprs_subscr_delete(s1);
259 s1 = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100260 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100261 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100262 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100263
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100264 /* Free entry 2 (GSM_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100265 gprs_subscr_delete(s2);
266 s2 = NULL;
267 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
268 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100269 assert_subscr(s3, imsi3);
270
271 /* Try to delete entry 3 */
272 OSMO_ASSERT(sgsn->cfg.subscriber_expiry_timeout == SGSN_TIMEOUT_NEVER);
273 gprs_subscr_delete(s3);
274 assert_subscr(s3, imsi3);
275 /* Process timeouts, this shouldn't delete s3 (SGSN_TIMEOUT_NEVER) */
276 osmo_timers_update();
277 assert_subscr(s3, imsi3);
278 s3 = subscr_get(s3);
279
280 /* Free entry 3 (TIMEOUT == 0) */
281 sgsn->cfg.subscriber_expiry_timeout = 0;
282 gprs_subscr_delete(s3);
283 assert_subscr(s3, imsi3);
284 /* Process timeouts, this should delete s3 */
285 osmo_timers_update();
286 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
287 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
288 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
289 sgsn->cfg.subscriber_expiry_timeout = saved_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100290
291 OSMO_ASSERT(llist_empty(&active_subscribers));
292
293 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
294}
295
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100296static void test_auth_triplets(void)
297{
298 struct gsm_subscriber *s1, *s1found;
299 const char *imsi1 = "1234567890";
300 struct gsm_auth_tuple *at;
301 struct sgsn_mm_ctx *ctx;
302 struct gprs_ra_id raid = { 0, };
303 uint32_t local_tlli = 0xffeeddcc;
304 struct gprs_llc_llme *llme;
305
306 printf("Testing authentication triplet handling\n");
307
308 /* Check for emptiness */
309 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
310
311 /* Allocate entry 1 */
312 s1 = gprs_subscr_get_or_create(imsi1);
313 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
314 s1found = gprs_subscr_get_by_imsi(imsi1);
315 OSMO_ASSERT(s1found == s1);
316 subscr_put(s1found);
317
318 /* Create a context */
319 OSMO_ASSERT(count(gprs_llme_list()) == 0);
320 ctx = alloc_mm_ctx(local_tlli, &raid);
321
322 /* Attach s1 to ctx */
323 ctx->subscr = subscr_get(s1);
324 ctx->subscr->sgsn_data->mm = ctx;
325
326 /* Try to get auth tuple */
327 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
328 OSMO_ASSERT(at == NULL);
329
330 /* Add triplets */
331 s1->sgsn_data->auth_triplets[0].key_seq = 0;
332 s1->sgsn_data->auth_triplets[1].key_seq = 1;
333 s1->sgsn_data->auth_triplets[2].key_seq = 2;
334
335 /* Try to get auth tuple */
336 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
337 OSMO_ASSERT(at != NULL);
338 OSMO_ASSERT(at->key_seq == 0);
339 OSMO_ASSERT(at->use_count == 1);
340 at = sgsn_auth_get_tuple(ctx, at->key_seq);
341 OSMO_ASSERT(at != NULL);
342 OSMO_ASSERT(at->key_seq == 1);
343 OSMO_ASSERT(at->use_count == 1);
344 at = sgsn_auth_get_tuple(ctx, at->key_seq);
345 OSMO_ASSERT(at != NULL);
346 OSMO_ASSERT(at->key_seq == 2);
347 OSMO_ASSERT(at->use_count == 1);
348 at = sgsn_auth_get_tuple(ctx, at->key_seq);
349 OSMO_ASSERT(at == NULL);
350
351 /* Free MM context and subscriber */
352 subscr_put(s1);
353 llme = ctx->llme;
354 sgsn_mm_ctx_free(ctx);
355 s1found = gprs_subscr_get_by_imsi(imsi1);
356 OSMO_ASSERT(s1found == NULL);
357 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
358}
359
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100360#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
361
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100362static int rx_gsup_message(const uint8_t *data, size_t data_len)
363{
364 struct msgb *msg;
365 int rc;
366
367 msg = msgb_alloc(1024, __func__);
368 msg->l2h = msgb_put(msg, data_len);
369 OSMO_ASSERT(msg->l2h != NULL);
370 memcpy(msg->l2h, data, data_len);
371 rc = gprs_subscr_rx_gsup_message(msg);
372 msgb_free(msg);
373
374 return rc;
375}
376
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100377static void test_subscriber_gsup(void)
378{
379 struct gsm_subscriber *s1, *s1found;
380 const char *imsi1 = "1234567890";
381 struct sgsn_mm_ctx *ctx;
382 struct gprs_ra_id raid = { 0, };
383 uint32_t local_tlli = 0xffeeddcc;
384 struct gprs_llc_llme *llme;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100385 int rc;
386
387 static const uint8_t send_auth_info_res[] = {
388 0x0a,
389 TEST_GSUP_IMSI1_IE,
390 0x03, 0x22, /* Auth tuple */
391 0x20, 0x10,
392 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
393 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
394 0x21, 0x04,
395 0x21, 0x22, 0x23, 0x24,
396 0x22, 0x08,
397 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
398 0x03, 0x22, /* Auth tuple */
399 0x20, 0x10,
400 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
401 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
402 0x21, 0x04,
403 0xa1, 0xa2, 0xa3, 0xa4,
404 0x22, 0x08,
405 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
406 };
407
408 static const uint8_t send_auth_info_err[] = {
409 0x09,
410 TEST_GSUP_IMSI1_IE,
411 0x02, 0x01, 0x07 /* GPRS not allowed */
412 };
413
414 static const uint8_t update_location_res[] = {
415 0x06,
416 TEST_GSUP_IMSI1_IE,
417 0x04, 0x00, /* PDP info complete */
418 0x05, 0x12,
419 0x10, 0x01, 0x01,
420 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
421 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
422 0x05, 0x11,
423 0x10, 0x01, 0x02,
424 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
425 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
426 };
427
428 static const uint8_t update_location_err[] = {
429 0x05,
430 TEST_GSUP_IMSI1_IE,
431 0x02, 0x01, 0x07 /* GPRS not allowed */
432 };
433
434 static const uint8_t location_cancellation_req[] = {
435 0x1c,
436 TEST_GSUP_IMSI1_IE,
437 0x06, 0x01, 0x00,
438 };
439
440 printf("Testing subcriber GSUP handling\n");
441
442 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
443
444 /* Check for emptiness */
445 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
446
447 /* Allocate entry 1 */
448 s1 = gprs_subscr_get_or_create(imsi1);
449 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
450 s1found = gprs_subscr_get_by_imsi(imsi1);
451 OSMO_ASSERT(s1found == s1);
452 subscr_put(s1found);
453
454 /* Create a context */
455 OSMO_ASSERT(count(gprs_llme_list()) == 0);
456 ctx = alloc_mm_ctx(local_tlli, &raid);
457 llme = ctx->llme;
458
459 /* Attach s1 to ctx */
460 ctx->subscr = subscr_get(s1);
461 ctx->subscr->sgsn_data->mm = ctx;
462
463 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100464 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100465 OSMO_ASSERT(rc >= 0);
466 OSMO_ASSERT(last_updated_subscr == s1);
467
468 /* Check triplets */
469 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
470 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
471 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
472
473 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100474 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100475 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100476 OSMO_ASSERT(last_updated_subscr == s1);
477
478 /* Check triplets */
479 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
480 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
481 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
482
483 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100484 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100485 OSMO_ASSERT(rc >= 0);
486 OSMO_ASSERT(last_updated_subscr == s1);
487
488 /* Check authorization */
489 OSMO_ASSERT(s1->authorized == 1);
490
491 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100492 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100493 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100494 OSMO_ASSERT(last_updated_subscr == s1);
495
496 /* Check authorization */
497 OSMO_ASSERT(s1->authorized == 0);
498
499 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100500 rc = rx_gsup_message(location_cancellation_req,
501 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100502 OSMO_ASSERT(rc >= 0);
503 OSMO_ASSERT(last_updated_subscr == s1);
504
505 /* Check cancellation result */
506 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
507 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
508
509 /* Free MM context and subscriber */
510 subscr_put(s1);
511 s1found = gprs_subscr_get_by_imsi(imsi1);
512 OSMO_ASSERT(s1found == NULL);
513 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
514
515 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
516}
517
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200518/*
519 * Test that a GMM Detach will remove the MMCTX and the
520 * associated LLME.
521 */
522static void test_gmm_detach(void)
523{
524 struct gprs_ra_id raid = { 0, };
525 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200526 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200527
528 printf("Testing GMM detach\n");
529
530 /* DTAP - Detach Request (MO) */
531 /* normal detach, power_off = 0 */
532 static const unsigned char detach_req[] = {
533 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
534 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
535 };
536
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200537 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200538
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100539 /* Create a context */
540 OSMO_ASSERT(count(gprs_llme_list()) == 0);
541 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200542
543 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100544 send_0408_message(ctx->llme, local_tlli,
545 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200546
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100547 /* verify that a single message (hopefully the Detach Accept) has been
548 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100549 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100550
551 /* verify that things are gone */
552 OSMO_ASSERT(count(gprs_llme_list()) == 0);
553 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
554 OSMO_ASSERT(!ictx);
555}
556
557/*
558 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
559 * will not sent a Detach Accept message (power_off = 1)
560 */
561static void test_gmm_detach_power_off(void)
562{
563 struct gprs_ra_id raid = { 0, };
564 struct sgsn_mm_ctx *ctx, *ictx;
565 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100566
567 printf("Testing GMM detach (power off)\n");
568
569 /* DTAP - Detach Request (MO) */
570 /* normal detach, power_off = 1 */
571 static const unsigned char detach_req[] = {
572 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
573 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
574 };
575
576 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
577
578 /* Create a context */
579 OSMO_ASSERT(count(gprs_llme_list()) == 0);
580 ctx = alloc_mm_ctx(local_tlli, &raid);
581
582 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100583 send_0408_message(ctx->llme, local_tlli,
584 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100585
586 /* verify that no message (and therefore no Detach Accept) has been
587 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100588 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100589
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200590 /* verify that things are gone */
591 OSMO_ASSERT(count(gprs_llme_list()) == 0);
592 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200593 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200594}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200595
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200596/*
597 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
598 */
599static void test_gmm_detach_no_mmctx(void)
600{
601 struct gprs_llc_lle *lle;
602 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200603
604 printf("Testing GMM detach (no MMCTX)\n");
605
606 /* DTAP - Detach Request (MO) */
607 /* normal detach, power_off = 0 */
608 static const unsigned char detach_req[] = {
609 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
610 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
611 };
612
613 /* Create an LLME */
614 OSMO_ASSERT(count(gprs_llme_list()) == 0);
615 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
616 lle = gprs_lle_get_or_create(local_tlli, 3);
617
618 OSMO_ASSERT(count(gprs_llme_list()) == 1);
619
620 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100621 send_0408_message(lle->llme, local_tlli,
622 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200623
624 /* verify that the LLME is gone */
625 OSMO_ASSERT(count(gprs_llme_list()) == 0);
626}
627
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100628/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100629 * Test that a single GMM Detach Accept message will not cause the SGSN to send
630 * any message or leave an MM context at the SGSN.
631 */
632static void test_gmm_detach_accept_unexpected(void)
633{
634 struct gprs_llc_lle *lle;
635 uint32_t local_tlli;
636
637 printf("Testing GMM detach accept (unexpected)\n");
638
639 /* DTAP - Detach Accept (MT) */
640 /* normal detach */
641 static const unsigned char detach_acc[] = {
642 0x08, 0x06
643 };
644
645 /* Create an LLME */
646 OSMO_ASSERT(count(gprs_llme_list()) == 0);
647 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
648 lle = gprs_lle_get_or_create(local_tlli, 3);
649
650 /* inject the detach */
651 send_0408_message(lle->llme, local_tlli,
652 detach_acc, ARRAY_SIZE(detach_acc));
653
654 /* verify that no message (and therefore no Status or XID reset) has been
655 * sent by the SGSN */
656 OSMO_ASSERT(sgsn_tx_counter == 0);
657
658 /* verify that things are gone */
659 OSMO_ASSERT(count(gprs_llme_list()) == 0);
660}
661
662/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100663 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
664 */
665static void test_gmm_status_no_mmctx(void)
666{
667 struct gprs_llc_lle *lle;
668 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100669
670 printf("Testing GMM Status (no MMCTX)\n");
671
672 /* DTAP - GMM Status, protocol error */
673 static const unsigned char gmm_status[] = {
674 0x08, 0x20, 0x6f
675 };
676
677 /* Create an LLME */
678 OSMO_ASSERT(count(gprs_llme_list()) == 0);
679 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
680 lle = gprs_lle_get_or_create(local_tlli, 3);
681
682 OSMO_ASSERT(count(gprs_llme_list()) == 1);
683
684 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100685 send_0408_message(lle->llme, local_tlli,
686 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100687
688 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100689 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100690
691 /* verify that the LLME is gone */
692 OSMO_ASSERT(count(gprs_llme_list()) == 0);
693}
694
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100695/*
696 * Test the GMM Attach procedure
697 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100698static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100699{
700 struct gprs_ra_id raid = { 0, };
701 struct sgsn_mm_ctx *ctx = NULL;
702 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100703 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100704 uint32_t foreign_tlli;
705 uint32_t local_tlli = 0;
706 struct gprs_llc_lle *lle;
707
708 /* DTAP - Attach Request */
709 /* The P-TMSI is not known by the SGSN */
710 static const unsigned char attach_req[] = {
711 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
712 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
713 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
714 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
715 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
716 };
717
718 /* DTAP - Identity Response IMEI */
719 static const unsigned char ident_resp_imei[] = {
720 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
721 0x56
722 };
723
724 /* DTAP - Identity Response IMSI */
725 static const unsigned char ident_resp_imsi[] = {
726 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
727 0x54
728 };
729
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100730 /* DTAP - Authentication and Ciphering Resp */
731 static const unsigned char auth_ciph_resp[] = {
732 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
733 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
734 };
735
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100736 /* DTAP - Attach Complete */
737 static const unsigned char attach_compl[] = {
738 0x08, 0x03
739 };
740
741 /* DTAP - Detach Request (MO) */
742 /* normal detach, power_off = 0 */
743 static const unsigned char detach_req[] = {
744 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
745 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
746 };
747
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100748 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100749
750 /* reset the PRNG used by sgsn_alloc_ptmsi */
751 srand(1);
752
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100753 ptmsi1 = sgsn_alloc_ptmsi();
754 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
755
756 /* reset the PRNG, so that the same P-TMSI sequence will be generated
757 * again */
758 srand(1);
759
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100760 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
761
762 /* Create a LLE/LLME */
763 OSMO_ASSERT(count(gprs_llme_list()) == 0);
764 lle = gprs_lle_get_or_create(foreign_tlli, 3);
765 OSMO_ASSERT(count(gprs_llme_list()) == 1);
766
767 /* inject the attach request */
768 send_0408_message(lle->llme, foreign_tlli,
769 attach_req, ARRAY_SIZE(attach_req));
770
771 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
772 OSMO_ASSERT(ctx != NULL);
773 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
774
775 /* we expect an identity request (IMEI) */
776 OSMO_ASSERT(sgsn_tx_counter == 1);
777
778 /* inject the identity response (IMEI) */
779 send_0408_message(ctx->llme, foreign_tlli,
780 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
781
782 /* we expect an identity request (IMSI) */
783 OSMO_ASSERT(sgsn_tx_counter == 1);
784
785 /* inject the identity response (IMSI) */
786 send_0408_message(ctx->llme, foreign_tlli,
787 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
788
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100789 /* check that the MM context has not been removed due to a failed
790 * authorization */
791 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
792
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100793 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100794
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100795retry_attach_req:
796
797 if (retry && sgsn_tx_counter == 0) {
798 fprintf(stderr, "Retrying attach request\n");
799 /* re-inject the attach request */
800 send_0408_message(lle->llme, foreign_tlli,
801 attach_req, ARRAY_SIZE(attach_req));
802 }
803
804 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
805 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100806
807 /* inject the auth & ciph response */
808 send_0408_message(ctx->llme, foreign_tlli,
809 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
810
811 /* check that the MM context has not been removed due to a
812 * failed authorization */
813 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
814 }
815
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100816 if (retry && sgsn_tx_counter == 0)
817 goto retry_attach_req;
818
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100819 /* we expect an attach accept/reject */
820 OSMO_ASSERT(sgsn_tx_counter == 1);
821
822 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100823 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100824
825 /* inject the attach complete */
826 send_0408_message(ctx->llme, local_tlli,
827 attach_compl, ARRAY_SIZE(attach_compl));
828
829 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
830
831 /* we don't expect a response */
832 OSMO_ASSERT(sgsn_tx_counter == 0);
833
834 /* inject the detach */
835 send_0408_message(ctx->llme, local_tlli,
836 detach_req, ARRAY_SIZE(detach_req));
837
838 /* verify that things are gone */
839 OSMO_ASSERT(count(gprs_llme_list()) == 0);
840 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
841 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100842}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100843
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100844static void test_gmm_attach_acl(void)
845{
846 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
847
848 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
849 sgsn_acl_add("123456789012345", &sgsn->cfg);
850 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100851 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100852 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100853
854 sgsn->cfg.auth_policy = saved_auth_policy;
855}
856
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100857int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100858 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100859 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100860 if (rc == -ENOTSUP) {
861 OSMO_ASSERT(mmctx->subscr);
862 gprs_subscr_update(mmctx->subscr);
863 }
864 return rc;
865};
866
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100867int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
868 gprs_subscr_update(mmctx->subscr);
869 return 0;
870};
871
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100872static void cleanup_subscr_by_imsi(const char *imsi)
873{
874 struct gsm_subscriber *subscr;
875
876 subscr = gprs_subscr_get_by_imsi(imsi);
877 OSMO_ASSERT(subscr != NULL);
Jacob Erlbecke1beb6f2015-01-08 14:13:46 +0100878 subscr->keep_in_ram = 0;
879 subscr_put(subscr);
880 subscr = gprs_subscr_get_by_imsi(imsi);
881 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100882}
883
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100884static void test_gmm_attach_subscr(void)
885{
886 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
887 struct gsm_subscriber *subscr;
888
889 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100890 subscr_request_update_location_cb = my_subscr_request_update_location;
891 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100892
893 subscr = gprs_subscr_get_or_create("123456789012345");
894 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100895 subscr->keep_in_ram = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100896 subscr_put(subscr);
897
898 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100899 test_gmm_attach(0);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100900
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100901 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100902
903 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100904 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
905 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100906}
907
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100908int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
909{
910 /* Fake an authentication */
911 OSMO_ASSERT(mmctx->subscr);
912 mmctx->is_authenticated = 1;
913 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100914
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100915 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100916};
917
918static void test_gmm_attach_subscr_fake_auth(void)
919{
920 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
921 struct gsm_subscriber *subscr;
922
923 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100924 subscr_request_update_location_cb = my_subscr_request_update_location;
925 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100926
927 subscr = gprs_subscr_get_or_create("123456789012345");
928 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100929 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100930 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100931 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100932 subscr_put(subscr);
933
934 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100935 test_gmm_attach(0);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100936
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100937 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100938
939 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100940 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
941 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
942}
943
944int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
945{
946 struct gsm_auth_tuple at = {
947 .sres = {0x51, 0xe5, 0x51, 0xe5},
948 .key_seq = 0
949 };
950
951 /* Fake an authentication */
952 OSMO_ASSERT(mmctx->subscr);
953 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
954
955 gprs_subscr_update_auth_info(mmctx->subscr);
956
957 return 0;
958};
959
960static void test_gmm_attach_subscr_real_auth(void)
961{
962 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
963 struct gsm_subscriber *subscr;
964
965 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
966 subscr_request_update_location_cb = my_subscr_request_update_location;
967 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
968
969 subscr = gprs_subscr_get_or_create("123456789012345");
970 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100971 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100972 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100973 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100974 subscr_put(subscr);
975
976 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100977 test_gmm_attach(0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100978
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100979 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100980
981 sgsn->cfg.auth_policy = saved_auth_policy;
982 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
983 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100984}
985
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100986#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
987 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
988
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100989static int auth_info_skip = 0;
990static int upd_loc_skip = 0;
991
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100992int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
993{
994 static const uint8_t send_auth_info_res[] = {
995 0x0a,
996 TEST_GSUP_IMSI_LONG_IE,
997 0x03, 0x22, /* Auth tuple */
998 0x20, 0x10,
999 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1000 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1001 0x21, 0x04,
1002 0x51, 0xe5, 0x51, 0xe5,
1003 0x22, 0x08,
1004 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1005 };
1006
1007 OSMO_ASSERT(mmctx->subscr);
1008
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001009 if (auth_info_skip > 0) {
1010 auth_info_skip -= 1;
1011 return -EAGAIN;
1012 }
1013
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001014 /* Fake an SendAuthInfoRes */
1015 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1016
1017 return 0;
1018};
1019
1020int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1021 static const uint8_t update_location_res[] = {
1022 0x06,
1023 TEST_GSUP_IMSI_LONG_IE,
1024 0x04, 0x00, /* PDP info complete */
1025 0x05, 0x12,
1026 0x10, 0x01, 0x01,
1027 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1028 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
1029 };
1030
1031 OSMO_ASSERT(mmctx->subscr);
1032
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001033 if (upd_loc_skip > 0) {
1034 upd_loc_skip -= 1;
1035 return -EAGAIN;
1036 }
1037
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001038 /* Fake an UpdateLocRes */
1039 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1040};
1041
1042
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001043static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001044{
1045 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1046 struct gsm_subscriber *subscr;
1047
1048 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1049 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1050 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001051 if (retry) {
1052 upd_loc_skip = 3;
1053 auth_info_skip = 3;
1054 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001055
1056 subscr = gprs_subscr_get_or_create("123456789012345");
1057 subscr->authorized = 1;
1058 sgsn->cfg.require_authentication = 1;
1059 sgsn->cfg.require_update_location = 1;
1060 subscr_put(subscr);
1061
1062 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001063 test_gmm_attach(retry);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001064
1065 subscr = gprs_subscr_get_by_imsi("123456789012345");
1066 OSMO_ASSERT(subscr != NULL);
1067 gprs_subscr_delete(subscr);
1068
1069 sgsn->cfg.auth_policy = saved_auth_policy;
1070 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1071 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001072 upd_loc_skip = 0;
1073 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001074}
1075
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001076/*
1077 * Test the GMM Rejects
1078 */
1079static void test_gmm_reject(void)
1080{
1081 struct gprs_ra_id raid = { 0, };
1082 struct sgsn_mm_ctx *ctx = NULL;
1083 uint32_t foreign_tlli;
1084 struct gprs_llc_lle *lle;
1085 int idx;
1086
1087 /* DTAP - Attach Request */
1088 /* Invalid MI length */
1089 static const unsigned char attach_req_inv_mi_len[] = {
1090 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1091 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1092 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1093 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1094 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1095 };
1096
1097 /* DTAP - Attach Request */
1098 /* Invalid MI type (IMEI) */
1099 static const unsigned char attach_req_inv_mi_type[] = {
1100 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1101 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1102 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1103 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1104 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1105 };
1106
1107 /* DTAP - Routing Area Update Request */
1108 static const unsigned char dtap_ra_upd_req[] = {
1109 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1110 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1111 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1112 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1113 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1114 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1115 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1116 };
1117
1118 /* DTAP - Routing Area Update Request */
1119 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1120 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1121 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1122 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1123 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1124 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1125 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1126 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1127 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1128 };
1129
1130 /* DTAP - Routing Area Update Request */
1131 /* Invalid cap length */
1132 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1133 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1134 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1137 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1138 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1139 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1140 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1141 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1142 };
1143
1144 struct test {
1145 const char *title;
1146 const unsigned char *msg;
1147 unsigned msg_len;
1148 unsigned num_resp;
1149
1150 };
1151 static struct test tests[] = {
1152 {
1153 .title = "Attach Request (invalid MI length)",
1154 .msg = attach_req_inv_mi_len,
1155 .msg_len = sizeof(attach_req_inv_mi_len),
1156 .num_resp = 1 /* Reject */
1157
1158 },
1159 {
1160 .title = "Attach Request (invalid MI type)",
1161 .msg = attach_req_inv_mi_type,
1162 .msg_len = sizeof(attach_req_inv_mi_type),
1163 .num_resp = 1 /* Reject */
1164 },
1165 {
1166 .title = "Routing Area Update Request (valid)",
1167 .msg = dtap_ra_upd_req,
1168 .msg_len = sizeof(dtap_ra_upd_req),
1169 .num_resp = 2 /* XID Reset + Reject */
1170 },
1171 {
1172 .title = "Routing Area Update Request (invalid type)",
1173 .msg = dtap_ra_upd_req_inv_type,
1174 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1175 .num_resp = 1 /* Reject */
1176 },
1177 {
1178 .title = "Routing Area Update Request (invalid CAP length)",
1179 .msg = dtap_ra_upd_req_inv_cap_len,
1180 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1181 .num_resp = 1 /* Reject */
1182 },
1183 };
1184
1185 printf("Testing GMM reject\n");
1186
1187 /* reset the PRNG used by sgsn_alloc_ptmsi */
1188 srand(1);
1189
1190 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1191
1192 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1193
1194 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1195 const struct test *test = &tests[idx];
1196 printf(" - %s\n", test->title);
1197
1198 /* Create a LLE/LLME */
1199 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1200 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1201
1202 /* Inject the Request message */
1203 send_0408_message(lle->llme, foreign_tlli,
1204 test->msg, test->msg_len);
1205
1206 /* We expect a Reject message */
1207 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1208 sgsn_tx_counter, test->num_resp);
1209 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1210
1211 /* verify that LLME/MM are removed */
1212 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1213 OSMO_ASSERT(ctx == NULL);
1214 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1215 }
1216}
1217
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001218/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001219 * Test cancellation of attached MM contexts
1220 */
1221static void test_gmm_cancel(void)
1222{
1223 struct gprs_ra_id raid = { 0, };
1224 struct sgsn_mm_ctx *ctx = NULL;
1225 struct sgsn_mm_ctx *ictx;
1226 uint32_t ptmsi1;
1227 uint32_t foreign_tlli;
1228 uint32_t local_tlli = 0;
1229 struct gprs_llc_lle *lle;
1230 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1231
1232 /* DTAP - Attach Request */
1233 /* The P-TMSI is not known by the SGSN */
1234 static const unsigned char attach_req[] = {
1235 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1236 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1237 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1238 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1239 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1240 };
1241
1242 /* DTAP - Identity Response IMEI */
1243 static const unsigned char ident_resp_imei[] = {
1244 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1245 0x56
1246 };
1247
1248 /* DTAP - Identity Response IMSI */
1249 static const unsigned char ident_resp_imsi[] = {
1250 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1251 0x54
1252 };
1253
1254 /* DTAP - Attach Complete */
1255 static const unsigned char attach_compl[] = {
1256 0x08, 0x03
1257 };
1258
1259 printf("Testing cancellation\n");
1260
1261 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1262
1263 /* reset the PRNG used by sgsn_alloc_ptmsi */
1264 srand(1);
1265
1266 ptmsi1 = sgsn_alloc_ptmsi();
1267 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1268
1269 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1270 * again */
1271 srand(1);
1272
1273 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1274
1275 /* Create a LLE/LLME */
1276 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1277 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1278 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1279
1280 /* inject the attach request */
1281 send_0408_message(lle->llme, foreign_tlli,
1282 attach_req, ARRAY_SIZE(attach_req));
1283
1284 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1285 OSMO_ASSERT(ctx != NULL);
1286 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1287
1288 /* we expect an identity request (IMEI) */
1289 OSMO_ASSERT(sgsn_tx_counter == 1);
1290
1291 /* inject the identity response (IMEI) */
1292 send_0408_message(ctx->llme, foreign_tlli,
1293 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1294
1295 /* we expect an identity request (IMSI) */
1296 OSMO_ASSERT(sgsn_tx_counter == 1);
1297
1298 /* inject the identity response (IMSI) */
1299 send_0408_message(ctx->llme, foreign_tlli,
1300 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1301
1302 /* check that the MM context has not been removed due to a failed
1303 * authorization */
1304 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1305
1306 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1307
1308 /* we expect an attach accept/reject */
1309 OSMO_ASSERT(sgsn_tx_counter == 1);
1310
1311 /* this has been randomly assigned by the SGSN */
1312 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1313
1314 /* inject the attach complete */
1315 send_0408_message(ctx->llme, local_tlli,
1316 attach_compl, ARRAY_SIZE(attach_compl));
1317
1318 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1319
1320 /* we don't expect a response */
1321 OSMO_ASSERT(sgsn_tx_counter == 0);
1322
1323 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001324 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001325
1326 /* verify that things are gone */
1327 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1328 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1329 OSMO_ASSERT(!ictx);
1330
1331 sgsn->cfg.auth_policy = saved_auth_policy;
1332}
1333
1334/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001335 * Test the dynamic allocation of P-TMSIs
1336 */
1337static void test_gmm_ptmsi_allocation(void)
1338{
1339 struct gprs_ra_id raid = { 0, };
1340 struct sgsn_mm_ctx *ctx = NULL;
1341 struct sgsn_mm_ctx *ictx;
1342 uint32_t foreign_tlli;
1343 uint32_t ptmsi1;
1344 uint32_t ptmsi2;
1345 uint32_t old_ptmsi;
1346 uint32_t local_tlli = 0;
1347 struct gprs_llc_lle *lle;
1348 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1349
1350 /* DTAP - Attach Request (IMSI 12131415161718) */
1351 static const unsigned char attach_req[] = {
1352 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1353 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1354 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1355 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1356 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1357 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1358 0x00,
1359 };
1360
1361 /* DTAP - Identity Response IMEI */
1362 static const unsigned char ident_resp_imei[] = {
1363 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1364 0x56
1365 };
1366
1367 /* DTAP - Attach Complete */
1368 static const unsigned char attach_compl[] = {
1369 0x08, 0x03
1370 };
1371
1372 /* DTAP - Routing Area Update Request */
1373 static const unsigned char ra_upd_req[] = {
1374 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1375 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1376 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1377 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1378 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1379 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1380 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1381 };
1382
1383 /* DTAP - Routing Area Update Complete */
1384 static const unsigned char ra_upd_complete[] = {
1385 0x08, 0x0a
1386 };
1387
1388 /* DTAP - Detach Request (MO) */
1389 /* normal detach, power_off = 1 */
1390 static const unsigned char detach_req[] = {
1391 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1392 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1393 };
1394
1395 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1396
1397 printf("Testing P-TMSI allocation\n");
1398
1399 printf(" - sgsn_alloc_ptmsi\n");
1400
1401 /* reset the PRNG used by sgsn_alloc_ptmsi */
1402 srand(1);
1403
1404 ptmsi1 = sgsn_alloc_ptmsi();
1405 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1406
1407 ptmsi2 = sgsn_alloc_ptmsi();
1408 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1409
1410 OSMO_ASSERT(ptmsi1 != ptmsi2);
1411
1412 printf(" - Repeated Attach Request\n");
1413
1414 /* reset the PRNG, so that the same P-TMSI will be generated
1415 * again */
1416 srand(1);
1417
1418 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1419
1420 /* Create a LLE/LLME */
1421 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1422 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1423 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1424
1425 /* inject the attach request */
1426 send_0408_message(lle->llme, foreign_tlli,
1427 attach_req, ARRAY_SIZE(attach_req));
1428
1429 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1430 OSMO_ASSERT(ctx != NULL);
1431 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1432 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1433
1434 old_ptmsi = ctx->p_tmsi_old;
1435
1436 /* we expect an identity request (IMEI) */
1437 OSMO_ASSERT(sgsn_tx_counter == 1);
1438
1439 /* inject the identity response (IMEI) */
1440 send_0408_message(ctx->llme, foreign_tlli,
1441 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1442
1443 /* check that the MM context has not been removed due to a failed
1444 * authorization */
1445 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1446
1447 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1448 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1449
1450 /* we expect an attach accept */
1451 OSMO_ASSERT(sgsn_tx_counter == 1);
1452
1453 /* we ignore this and send the attach again */
1454 send_0408_message(lle->llme, foreign_tlli,
1455 attach_req, ARRAY_SIZE(attach_req));
1456
1457 /* the allocated P-TMSI should be the same */
1458 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1459 OSMO_ASSERT(ctx != NULL);
1460 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1461 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1462 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1463
1464 /* inject the attach complete */
1465 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1466 send_0408_message(ctx->llme, local_tlli,
1467 attach_compl, ARRAY_SIZE(attach_compl));
1468
1469 /* we don't expect a response */
1470 OSMO_ASSERT(sgsn_tx_counter == 0);
1471
1472 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1473 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1474 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1475
1476 printf(" - Repeated RA Update Request\n");
1477
1478 /* inject the RA update request */
1479 send_0408_message(ctx->llme, local_tlli,
1480 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1481
1482 /* we expect an RA update accept */
1483 OSMO_ASSERT(sgsn_tx_counter == 1);
1484
1485 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1486 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1487 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1488
1489 /* repeat the RA update request */
1490 send_0408_message(ctx->llme, local_tlli,
1491 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1492
1493 /* we expect an RA update accept */
1494 OSMO_ASSERT(sgsn_tx_counter == 1);
1495
1496 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1497 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1498 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1499
1500 /* inject the RA update complete */
1501 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1502 send_0408_message(ctx->llme, local_tlli,
1503 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1504
1505 /* we don't expect a response */
1506 OSMO_ASSERT(sgsn_tx_counter == 0);
1507
1508 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1509 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1510 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1511
1512 /* inject the detach */
1513 send_0408_message(ctx->llme, local_tlli,
1514 detach_req, ARRAY_SIZE(detach_req));
1515
1516 /* verify that things are gone */
1517 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1518 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1519 OSMO_ASSERT(!ictx);
1520
1521 sgsn->cfg.auth_policy = saved_auth_policy;
1522}
1523
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001524static struct log_info_cat gprs_categories[] = {
1525 [DMM] = {
1526 .name = "DMM",
1527 .description = "Layer3 Mobility Management (MM)",
1528 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001529 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001530 },
1531 [DPAG] = {
1532 .name = "DPAG",
1533 .description = "Paging Subsystem",
1534 .color = "\033[1;38m",
1535 .enabled = 1, .loglevel = LOGL_NOTICE,
1536 },
1537 [DMEAS] = {
1538 .name = "DMEAS",
1539 .description = "Radio Measurement Processing",
1540 .enabled = 0, .loglevel = LOGL_NOTICE,
1541 },
1542 [DREF] = {
1543 .name = "DREF",
1544 .description = "Reference Counting",
1545 .enabled = 0, .loglevel = LOGL_NOTICE,
1546 },
1547 [DGPRS] = {
1548 .name = "DGPRS",
1549 .description = "GPRS Packet Service",
1550 .enabled = 1, .loglevel = LOGL_DEBUG,
1551 },
1552 [DNS] = {
1553 .name = "DNS",
1554 .description = "GPRS Network Service (NS)",
1555 .enabled = 1, .loglevel = LOGL_INFO,
1556 },
1557 [DBSSGP] = {
1558 .name = "DBSSGP",
1559 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1560 .enabled = 1, .loglevel = LOGL_DEBUG,
1561 },
1562 [DLLC] = {
1563 .name = "DLLC",
1564 .description = "GPRS Logical Link Control Protocol (LLC)",
1565 .enabled = 1, .loglevel = LOGL_DEBUG,
1566 },
1567 [DSNDCP] = {
1568 .name = "DSNDCP",
1569 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1570 .enabled = 1, .loglevel = LOGL_DEBUG,
1571 },
1572};
1573
1574static struct log_info info = {
1575 .cat = gprs_categories,
1576 .num_cat = ARRAY_SIZE(gprs_categories),
1577};
1578
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001579int main(int argc, char **argv)
1580{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001581 osmo_init_logging(&info);
1582 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1583 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1584
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001585 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001586 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001587
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001588 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001589 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001590 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001591 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001592 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001593 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001594 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001595 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001596 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001597 test_gmm_attach_acl();
1598 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001599 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001600 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001601 test_gmm_attach_subscr_gsup_auth(0);
1602 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001603 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001604 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001605 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001606 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001607
1608 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01001609 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001610 return 0;
1611}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001612
1613
1614/* stubs */
1615struct osmo_prim_hdr;
1616int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1617{
1618 abort();
1619}