blob: b83cfaef21c0d13fd4054b512c445b7640b7089b [file] [log] [blame]
Holger Hans Peter Freyther232f6212014-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 Freyther49dbcd92014-10-02 21:27:24 +020022#include <openbsc/gprs_llc.h>
23#include <openbsc/sgsn.h>
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +020024#include <openbsc/gprs_gmm.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020025#include <openbsc/debug.h>
Jacob Erlbecke8b69682014-11-12 10:12:11 +010026#include <openbsc/gsm_subscriber.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020027
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010028#include <osmocom/gprs/gprs_bssgp.h>
29
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020030#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeck092bbc82015-01-05 18:57:32 +010031#include <openbsc/gsm_04_08_gprs.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020032
33#include <osmocom/core/application.h>
34#include <osmocom/core/msgb.h>
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010035#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020036
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +020037#include <stdio.h>
38
Holger Hans Peter Freyther49dbcd92014-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 Erlbeckd7b77732014-11-04 10:08:37 +010046 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020047 },
48};
49struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck0b2da872014-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 Erlbeck6e6b3302015-01-13 11:56:28 +010057 msgb_free(msg);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010058 return 0;
59}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020060
Jacob Erlbecke8b69682014-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 Erlbeck828059f2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +010076
Jacob Erlbeck828059f2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +010088};
Jacob Erlbecke8b69682014-11-12 10:12:11 +010089
Holger Hans Peter Freyther49dbcd92014-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 Freyther94246842014-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 Erlbeckf43a2992014-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 Erlbeck75488292014-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 Freyther49dbcd92014-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 Erlbecke8b69682014-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 Erlbeckb1332b62014-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 Erlbeck5641cfc2014-12-12 15:01:37 +0100327#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
328
Jacob Erlbeckb5c51432014-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 Erlbeck5641cfc2014-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 Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100431 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100441 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100442 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100451 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100459 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100460 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100467 rc = rx_gsup_message(location_cancellation_req,
468 sizeof(location_cancellation_req));
Jacob Erlbeck5641cfc2014-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 Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200493 uint32_t local_tlli;
Holger Hans Peter Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200504 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200505
Jacob Erlbeckf43a2992014-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 Freyther94246842014-10-02 22:24:47 +0200509
510 /* inject the detach */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100511 send_0408_message(ctx->llme, local_tlli,
512 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200513
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100514 /* verify that a single message (hopefully the Detach Accept) has been
515 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100516 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck0b2da872014-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 Erlbeck0b2da872014-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 Erlbeck75488292014-10-29 10:31:18 +0100550 send_0408_message(ctx->llme, local_tlli,
551 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100552
553 /* verify that no message (and therefore no Detach Accept) has been
554 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100555 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100556
Holger Hans Peter Freyther94246842014-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 Erlbeck12396bd2014-09-30 13:51:45 +0200560 OSMO_ASSERT(!ictx);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200561}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200562
Jacob Erlbeck42d284f2014-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 Erlbeck42d284f2014-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 Erlbeck75488292014-10-29 10:31:18 +0100588 send_0408_message(lle->llme, local_tlli,
589 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200590
591 /* verify that the LLME is gone */
592 OSMO_ASSERT(count(gprs_llme_list()) == 0);
593}
594
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100595/*
Jacob Erlbeck021a0d12014-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 Erlbeckb35ee6b2014-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 Erlbeckb35ee6b2014-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 Erlbeck75488292014-10-29 10:31:18 +0100652 send_0408_message(lle->llme, local_tlli,
653 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100654
655 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100656 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100657
658 /* verify that the LLME is gone */
659 OSMO_ASSERT(count(gprs_llme_list()) == 0);
660}
661
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100662/*
663 * Test the GMM Attach procedure
664 */
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100665static void test_gmm_attach(int retry)
Jacob Erlbeck7c24b3e2014-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 Erlbeck0a2c7912014-11-24 14:40:28 +0100670 uint32_t ptmsi1;
Jacob Erlbeck7c24b3e2014-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 Erlbeck828059f2014-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 Erlbeck7c24b3e2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100715 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100716
717 /* reset the PRNG used by sgsn_alloc_ptmsi */
718 srand(1);
719
Jacob Erlbeck0a2c7912014-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 Erlbeck7c24b3e2014-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 Erlbeck7c24b3e2014-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 Erlbeck67318ef2014-10-28 16:23:46 +0100760 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100761
Jacob Erlbeck803ebfa2014-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 Erlbeck828059f2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100783 if (retry && sgsn_tx_counter == 0)
784 goto retry_attach_req;
785
Jacob Erlbeck7c24b3e2014-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 Erlbeck0a2c7912014-11-24 14:40:28 +0100790 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck7c24b3e2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +0100809}
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100810
Jacob Erlbeckd04f7cc2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100818 test_gmm_attach(0);
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100819 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100820
821 sgsn->cfg.auth_policy = saved_auth_policy;
822}
823
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100824int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100825 int rc;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100826 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckd04f7cc2014-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 Erlbeck828059f2014-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 Erlbeck03386f62015-01-08 14:08:16 +0100839static void cleanup_subscr_by_imsi(const char *imsi)
840{
841 struct gsm_subscriber *subscr;
842
843 subscr = gprs_subscr_get_by_imsi(imsi);
844 OSMO_ASSERT(subscr != NULL);
Jacob Erlbeckdc7e8b92015-01-08 14:13:46 +0100845 subscr->keep_in_ram = 0;
846 subscr_put(subscr);
847 subscr = gprs_subscr_get_by_imsi(imsi);
848 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100849}
850
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100851static void test_gmm_attach_subscr(void)
852{
853 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
854 struct gsm_subscriber *subscr;
855
856 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100857 subscr_request_update_location_cb = my_subscr_request_update_location;
858 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100859
860 subscr = gprs_subscr_get_or_create("123456789012345");
861 subscr->authorized = 1;
862 subscr_put(subscr);
863
864 printf("Auth policy 'remote': ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100865 test_gmm_attach(0);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100866
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100867 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100868
869 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100870 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
871 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100872}
873
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100874int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
875{
876 /* Fake an authentication */
877 OSMO_ASSERT(mmctx->subscr);
878 mmctx->is_authenticated = 1;
879 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100880
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100881 return 0;
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100882};
883
884static void test_gmm_attach_subscr_fake_auth(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 Erlbeck828059f2014-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_fake_auth;
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100892
893 subscr = gprs_subscr_get_or_create("123456789012345");
894 subscr->authorized = 1;
Jacob Erlbeck16b17ed2014-12-17 13:20:08 +0100895 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck6ff7f642014-12-19 18:08:48 +0100896 sgsn->cfg.require_update_location = 1;
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100897 subscr_put(subscr);
898
899 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100900 test_gmm_attach(0);
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100901
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100902 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100903
904 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100905 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
906 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
907}
908
909int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
910{
911 struct gsm_auth_tuple at = {
912 .sres = {0x51, 0xe5, 0x51, 0xe5},
913 .key_seq = 0
914 };
915
916 /* Fake an authentication */
917 OSMO_ASSERT(mmctx->subscr);
918 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
919
920 gprs_subscr_update_auth_info(mmctx->subscr);
921
922 return 0;
923};
924
925static void test_gmm_attach_subscr_real_auth(void)
926{
927 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
928 struct gsm_subscriber *subscr;
929
930 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
931 subscr_request_update_location_cb = my_subscr_request_update_location;
932 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
933
934 subscr = gprs_subscr_get_or_create("123456789012345");
935 subscr->authorized = 1;
Jacob Erlbeck16b17ed2014-12-17 13:20:08 +0100936 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck6ff7f642014-12-19 18:08:48 +0100937 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100938 subscr_put(subscr);
939
940 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100941 test_gmm_attach(0);
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100942
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100943 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100944
945 sgsn->cfg.auth_policy = saved_auth_policy;
946 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
947 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100948}
949
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100950#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
951 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
952
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100953static int auth_info_skip = 0;
954static int upd_loc_skip = 0;
955
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100956int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
957{
958 static const uint8_t send_auth_info_res[] = {
959 0x0a,
960 TEST_GSUP_IMSI_LONG_IE,
961 0x03, 0x22, /* Auth tuple */
962 0x20, 0x10,
963 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
964 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
965 0x21, 0x04,
966 0x51, 0xe5, 0x51, 0xe5,
967 0x22, 0x08,
968 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
969 };
970
971 OSMO_ASSERT(mmctx->subscr);
972
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100973 if (auth_info_skip > 0) {
974 auth_info_skip -= 1;
975 return -EAGAIN;
976 }
977
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100978 /* Fake an SendAuthInfoRes */
979 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
980
981 return 0;
982};
983
984int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
985 static const uint8_t update_location_res[] = {
986 0x06,
987 TEST_GSUP_IMSI_LONG_IE,
988 0x04, 0x00, /* PDP info complete */
989 0x05, 0x12,
990 0x10, 0x01, 0x01,
991 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
992 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
993 };
994
995 OSMO_ASSERT(mmctx->subscr);
996
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100997 if (upd_loc_skip > 0) {
998 upd_loc_skip -= 1;
999 return -EAGAIN;
1000 }
1001
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001002 /* Fake an UpdateLocRes */
1003 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1004};
1005
1006
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001007static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001008{
1009 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1010 struct gsm_subscriber *subscr;
1011
1012 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1013 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1014 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001015 if (retry) {
1016 upd_loc_skip = 3;
1017 auth_info_skip = 3;
1018 }
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001019
1020 subscr = gprs_subscr_get_or_create("123456789012345");
1021 subscr->authorized = 1;
1022 sgsn->cfg.require_authentication = 1;
1023 sgsn->cfg.require_update_location = 1;
1024 subscr_put(subscr);
1025
1026 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001027 test_gmm_attach(retry);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001028
1029 subscr = gprs_subscr_get_by_imsi("123456789012345");
1030 OSMO_ASSERT(subscr != NULL);
1031 gprs_subscr_delete(subscr);
1032
1033 sgsn->cfg.auth_policy = saved_auth_policy;
1034 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1035 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001036 upd_loc_skip = 0;
1037 auth_info_skip = 0;
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001038}
1039
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001040/*
1041 * Test the GMM Rejects
1042 */
1043static void test_gmm_reject(void)
1044{
1045 struct gprs_ra_id raid = { 0, };
1046 struct sgsn_mm_ctx *ctx = NULL;
1047 uint32_t foreign_tlli;
1048 struct gprs_llc_lle *lle;
1049 int idx;
1050
1051 /* DTAP - Attach Request */
1052 /* Invalid MI length */
1053 static const unsigned char attach_req_inv_mi_len[] = {
1054 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1055 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1056 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1057 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1058 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1059 };
1060
1061 /* DTAP - Attach Request */
1062 /* Invalid MI type (IMEI) */
1063 static const unsigned char attach_req_inv_mi_type[] = {
1064 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1065 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1066 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1067 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1068 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1069 };
1070
1071 /* DTAP - Routing Area Update Request */
1072 static const unsigned char dtap_ra_upd_req[] = {
1073 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1074 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1075 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1076 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1077 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1078 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1079 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1080 };
1081
1082 /* DTAP - Routing Area Update Request */
1083 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1084 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1085 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1086 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1087 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1088 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1089 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1090 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1091 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1092 };
1093
1094 /* DTAP - Routing Area Update Request */
1095 /* Invalid cap length */
1096 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1097 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1098 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1099 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1101 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1102 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1103 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1104 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1105 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1106 };
1107
1108 struct test {
1109 const char *title;
1110 const unsigned char *msg;
1111 unsigned msg_len;
1112 unsigned num_resp;
1113
1114 };
1115 static struct test tests[] = {
1116 {
1117 .title = "Attach Request (invalid MI length)",
1118 .msg = attach_req_inv_mi_len,
1119 .msg_len = sizeof(attach_req_inv_mi_len),
1120 .num_resp = 1 /* Reject */
1121
1122 },
1123 {
1124 .title = "Attach Request (invalid MI type)",
1125 .msg = attach_req_inv_mi_type,
1126 .msg_len = sizeof(attach_req_inv_mi_type),
1127 .num_resp = 1 /* Reject */
1128 },
1129 {
1130 .title = "Routing Area Update Request (valid)",
1131 .msg = dtap_ra_upd_req,
1132 .msg_len = sizeof(dtap_ra_upd_req),
1133 .num_resp = 2 /* XID Reset + Reject */
1134 },
1135 {
1136 .title = "Routing Area Update Request (invalid type)",
1137 .msg = dtap_ra_upd_req_inv_type,
1138 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1139 .num_resp = 1 /* Reject */
1140 },
1141 {
1142 .title = "Routing Area Update Request (invalid CAP length)",
1143 .msg = dtap_ra_upd_req_inv_cap_len,
1144 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1145 .num_resp = 1 /* Reject */
1146 },
1147 };
1148
1149 printf("Testing GMM reject\n");
1150
1151 /* reset the PRNG used by sgsn_alloc_ptmsi */
1152 srand(1);
1153
1154 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1155
1156 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1157
1158 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1159 const struct test *test = &tests[idx];
1160 printf(" - %s\n", test->title);
1161
1162 /* Create a LLE/LLME */
1163 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1164 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1165
1166 /* Inject the Request message */
1167 send_0408_message(lle->llme, foreign_tlli,
1168 test->msg, test->msg_len);
1169
1170 /* We expect a Reject message */
1171 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1172 sgsn_tx_counter, test->num_resp);
1173 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1174
1175 /* verify that LLME/MM are removed */
1176 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1177 OSMO_ASSERT(ctx == NULL);
1178 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1179 }
1180}
1181
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001182/*
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001183 * Test cancellation of attached MM contexts
1184 */
1185static void test_gmm_cancel(void)
1186{
1187 struct gprs_ra_id raid = { 0, };
1188 struct sgsn_mm_ctx *ctx = NULL;
1189 struct sgsn_mm_ctx *ictx;
1190 uint32_t ptmsi1;
1191 uint32_t foreign_tlli;
1192 uint32_t local_tlli = 0;
1193 struct gprs_llc_lle *lle;
1194 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1195
1196 /* DTAP - Attach Request */
1197 /* The P-TMSI is not known by the SGSN */
1198 static const unsigned char attach_req[] = {
1199 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1200 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1201 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1202 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1203 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1204 };
1205
1206 /* DTAP - Identity Response IMEI */
1207 static const unsigned char ident_resp_imei[] = {
1208 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1209 0x56
1210 };
1211
1212 /* DTAP - Identity Response IMSI */
1213 static const unsigned char ident_resp_imsi[] = {
1214 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1215 0x54
1216 };
1217
1218 /* DTAP - Attach Complete */
1219 static const unsigned char attach_compl[] = {
1220 0x08, 0x03
1221 };
1222
1223 printf("Testing cancellation\n");
1224
1225 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1226
1227 /* reset the PRNG used by sgsn_alloc_ptmsi */
1228 srand(1);
1229
1230 ptmsi1 = sgsn_alloc_ptmsi();
1231 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1232
1233 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1234 * again */
1235 srand(1);
1236
1237 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1238
1239 /* Create a LLE/LLME */
1240 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1241 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1242 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1243
1244 /* inject the attach request */
1245 send_0408_message(lle->llme, foreign_tlli,
1246 attach_req, ARRAY_SIZE(attach_req));
1247
1248 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1249 OSMO_ASSERT(ctx != NULL);
1250 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1251
1252 /* we expect an identity request (IMEI) */
1253 OSMO_ASSERT(sgsn_tx_counter == 1);
1254
1255 /* inject the identity response (IMEI) */
1256 send_0408_message(ctx->llme, foreign_tlli,
1257 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1258
1259 /* we expect an identity request (IMSI) */
1260 OSMO_ASSERT(sgsn_tx_counter == 1);
1261
1262 /* inject the identity response (IMSI) */
1263 send_0408_message(ctx->llme, foreign_tlli,
1264 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1265
1266 /* check that the MM context has not been removed due to a failed
1267 * authorization */
1268 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1269
1270 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1271
1272 /* we expect an attach accept/reject */
1273 OSMO_ASSERT(sgsn_tx_counter == 1);
1274
1275 /* this has been randomly assigned by the SGSN */
1276 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1277
1278 /* inject the attach complete */
1279 send_0408_message(ctx->llme, local_tlli,
1280 attach_compl, ARRAY_SIZE(attach_compl));
1281
1282 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1283
1284 /* we don't expect a response */
1285 OSMO_ASSERT(sgsn_tx_counter == 0);
1286
1287 /* cancel */
Jacob Erlbeck41010082015-01-05 17:51:17 +01001288 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001289
1290 /* verify that things are gone */
1291 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1292 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1293 OSMO_ASSERT(!ictx);
1294
1295 sgsn->cfg.auth_policy = saved_auth_policy;
1296}
1297
1298/*
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001299 * Test the dynamic allocation of P-TMSIs
1300 */
1301static void test_gmm_ptmsi_allocation(void)
1302{
1303 struct gprs_ra_id raid = { 0, };
1304 struct sgsn_mm_ctx *ctx = NULL;
1305 struct sgsn_mm_ctx *ictx;
1306 uint32_t foreign_tlli;
1307 uint32_t ptmsi1;
1308 uint32_t ptmsi2;
1309 uint32_t old_ptmsi;
1310 uint32_t local_tlli = 0;
1311 struct gprs_llc_lle *lle;
1312 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1313
1314 /* DTAP - Attach Request (IMSI 12131415161718) */
1315 static const unsigned char attach_req[] = {
1316 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1317 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1318 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1319 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1320 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1321 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1322 0x00,
1323 };
1324
1325 /* DTAP - Identity Response IMEI */
1326 static const unsigned char ident_resp_imei[] = {
1327 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1328 0x56
1329 };
1330
1331 /* DTAP - Attach Complete */
1332 static const unsigned char attach_compl[] = {
1333 0x08, 0x03
1334 };
1335
1336 /* DTAP - Routing Area Update Request */
1337 static const unsigned char ra_upd_req[] = {
1338 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1339 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1340 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1341 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1342 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1343 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1344 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1345 };
1346
1347 /* DTAP - Routing Area Update Complete */
1348 static const unsigned char ra_upd_complete[] = {
1349 0x08, 0x0a
1350 };
1351
1352 /* DTAP - Detach Request (MO) */
1353 /* normal detach, power_off = 1 */
1354 static const unsigned char detach_req[] = {
1355 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1356 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1357 };
1358
1359 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1360
1361 printf("Testing P-TMSI allocation\n");
1362
1363 printf(" - sgsn_alloc_ptmsi\n");
1364
1365 /* reset the PRNG used by sgsn_alloc_ptmsi */
1366 srand(1);
1367
1368 ptmsi1 = sgsn_alloc_ptmsi();
1369 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1370
1371 ptmsi2 = sgsn_alloc_ptmsi();
1372 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1373
1374 OSMO_ASSERT(ptmsi1 != ptmsi2);
1375
1376 printf(" - Repeated Attach Request\n");
1377
1378 /* reset the PRNG, so that the same P-TMSI will be generated
1379 * again */
1380 srand(1);
1381
1382 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1383
1384 /* Create a LLE/LLME */
1385 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1386 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1387 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1388
1389 /* inject the attach request */
1390 send_0408_message(lle->llme, foreign_tlli,
1391 attach_req, ARRAY_SIZE(attach_req));
1392
1393 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1394 OSMO_ASSERT(ctx != NULL);
1395 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1396 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1397
1398 old_ptmsi = ctx->p_tmsi_old;
1399
1400 /* we expect an identity request (IMEI) */
1401 OSMO_ASSERT(sgsn_tx_counter == 1);
1402
1403 /* inject the identity response (IMEI) */
1404 send_0408_message(ctx->llme, foreign_tlli,
1405 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1406
1407 /* check that the MM context has not been removed due to a failed
1408 * authorization */
1409 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1410
1411 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1412 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1413
1414 /* we expect an attach accept */
1415 OSMO_ASSERT(sgsn_tx_counter == 1);
1416
1417 /* we ignore this and send the attach again */
1418 send_0408_message(lle->llme, foreign_tlli,
1419 attach_req, ARRAY_SIZE(attach_req));
1420
1421 /* the allocated P-TMSI should be the same */
1422 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1423 OSMO_ASSERT(ctx != NULL);
1424 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1425 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1426 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1427
1428 /* inject the attach complete */
1429 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1430 send_0408_message(ctx->llme, local_tlli,
1431 attach_compl, ARRAY_SIZE(attach_compl));
1432
1433 /* we don't expect a response */
1434 OSMO_ASSERT(sgsn_tx_counter == 0);
1435
1436 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1437 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1438 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1439
1440 printf(" - Repeated RA Update Request\n");
1441
1442 /* inject the RA update request */
1443 send_0408_message(ctx->llme, local_tlli,
1444 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1445
1446 /* we expect an RA update accept */
1447 OSMO_ASSERT(sgsn_tx_counter == 1);
1448
1449 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1450 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1451 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1452
1453 /* repeat the RA update request */
1454 send_0408_message(ctx->llme, local_tlli,
1455 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1456
1457 /* we expect an RA update accept */
1458 OSMO_ASSERT(sgsn_tx_counter == 1);
1459
1460 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1461 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1462 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1463
1464 /* inject the RA update complete */
1465 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1466 send_0408_message(ctx->llme, local_tlli,
1467 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
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 == ptmsi2);
1475
1476 /* inject the detach */
1477 send_0408_message(ctx->llme, local_tlli,
1478 detach_req, ARRAY_SIZE(detach_req));
1479
1480 /* verify that things are gone */
1481 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1482 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1483 OSMO_ASSERT(!ictx);
1484
1485 sgsn->cfg.auth_policy = saved_auth_policy;
1486}
1487
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001488static struct log_info_cat gprs_categories[] = {
1489 [DMM] = {
1490 .name = "DMM",
1491 .description = "Layer3 Mobility Management (MM)",
1492 .color = "\033[1;33m",
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001493 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001494 },
1495 [DPAG] = {
1496 .name = "DPAG",
1497 .description = "Paging Subsystem",
1498 .color = "\033[1;38m",
1499 .enabled = 1, .loglevel = LOGL_NOTICE,
1500 },
1501 [DMEAS] = {
1502 .name = "DMEAS",
1503 .description = "Radio Measurement Processing",
1504 .enabled = 0, .loglevel = LOGL_NOTICE,
1505 },
1506 [DREF] = {
1507 .name = "DREF",
1508 .description = "Reference Counting",
1509 .enabled = 0, .loglevel = LOGL_NOTICE,
1510 },
1511 [DGPRS] = {
1512 .name = "DGPRS",
1513 .description = "GPRS Packet Service",
1514 .enabled = 1, .loglevel = LOGL_DEBUG,
1515 },
1516 [DNS] = {
1517 .name = "DNS",
1518 .description = "GPRS Network Service (NS)",
1519 .enabled = 1, .loglevel = LOGL_INFO,
1520 },
1521 [DBSSGP] = {
1522 .name = "DBSSGP",
1523 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1524 .enabled = 1, .loglevel = LOGL_DEBUG,
1525 },
1526 [DLLC] = {
1527 .name = "DLLC",
1528 .description = "GPRS Logical Link Control Protocol (LLC)",
1529 .enabled = 1, .loglevel = LOGL_DEBUG,
1530 },
1531 [DSNDCP] = {
1532 .name = "DSNDCP",
1533 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1534 .enabled = 1, .loglevel = LOGL_DEBUG,
1535 },
1536};
1537
1538static struct log_info info = {
1539 .cat = gprs_categories,
1540 .num_cat = ARRAY_SIZE(gprs_categories),
1541};
1542
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001543int main(int argc, char **argv)
1544{
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001545 osmo_init_logging(&info);
1546 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1547 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1548
Jacob Erlbeckb2acd742014-11-13 10:48:39 +01001549 sgsn_auth_init();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001550 gprs_subscr_init(sgsn);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001551
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001552 test_llme();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001553 test_subscriber();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +01001554 test_auth_triplets();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +01001555 test_subscriber_gsup();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +02001556 test_gmm_detach();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +01001557 test_gmm_detach_power_off();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001558 test_gmm_detach_no_mmctx();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +01001559 test_gmm_detach_accept_unexpected();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001560 test_gmm_status_no_mmctx();
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +01001561 test_gmm_attach_acl();
1562 test_gmm_attach_subscr();
Jacob Erlbeckd8126992014-12-08 15:26:47 +01001563 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck828059f2014-11-28 14:55:25 +01001564 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001565 test_gmm_attach_subscr_gsup_auth(0);
1566 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001567 test_gmm_reject();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001568 test_gmm_cancel();
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001569 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001570 printf("Done\n");
Jacob Erlbeck80dbcf12015-01-13 11:46:32 +01001571
1572 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeck6e6b3302015-01-13 11:56:28 +01001573 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001574 return 0;
1575}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001576
1577
1578/* stubs */
1579struct osmo_prim_hdr;
1580int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1581{
1582 abort();
1583}