blob: d6126523e328f0179269177cdf6f40fb8dd99ab3 [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>
Jacob Erlbeckc157ee72015-01-09 15:07:16 +010027#include <openbsc/gprs_gsup_messages.h>
28#include <openbsc/gprs_gsup_client.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020029
Jacob Erlbeck189999d2014-10-27 14:34:13 +010030#include <osmocom/gprs/gprs_bssgp.h>
31
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020032#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeckbce20612015-01-05 18:57:32 +010033#include <openbsc/gsm_04_08_gprs.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020034
35#include <osmocom/core/application.h>
36#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010037#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020038
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020039#include <stdio.h>
40
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020041extern void *tall_msgb_ctx;
42
43void *tall_bsc_ctx;
44static struct sgsn_instance sgsn_inst = {
45 .config_file = "osmo_sgsn.cfg",
46 .cfg = {
47 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010048 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +010049 .subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020050 },
51};
52struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010053unsigned sgsn_tx_counter = 0;
54
55/* override */
56int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
57 struct bssgp_dl_ud_par *dup)
58{
59 sgsn_tx_counter += 1;
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +010060 msgb_free(msg);
Jacob Erlbeck189999d2014-10-27 14:34:13 +010061 return 0;
62}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020063
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010064/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
65void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *, struct gsm_subscriber *);
66void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *, struct gsm_subscriber *) =
67 &__real_sgsn_update_subscriber_data;
68
69void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
70 struct gsm_subscriber *subscr)
71{
72 (*update_subscriber_data_cb)(mmctx, subscr);
73}
74
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010075/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
76int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
77int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
78 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010079
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010080int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
81 return (*subscr_request_update_location_cb)(mmctx);
82};
83
84/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
85int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
86int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
87 &__real_gprs_subscr_request_auth_info;
88
89int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
90 return (*subscr_request_auth_info_cb)(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010091};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010092
Jacob Erlbeckc157ee72015-01-09 15:07:16 +010093/* override, requires '-Wl,--wrap=gprs_gsup_client_send' */
94int __real_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg);
95int (*gprs_gsup_client_send_cb)(struct gprs_gsup_client *gsupc, struct msgb *msg) =
96 &__real_gprs_gsup_client_send;
97
98int __wrap_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
99{
100 return (*gprs_gsup_client_send_cb)(gsupc, msg);
101};
102
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200103static int count(struct llist_head *head)
104{
105 struct llist_head *cur;
106 int count = 0;
107
108 llist_for_each(cur, head)
109 count += 1;
110
111 return count;
112}
113
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200114static struct msgb *create_msg(const uint8_t *data, size_t len)
115{
116 struct msgb *msg = msgb_alloc(len + 8, "test message");
117 msg->l1h = msgb_put(msg, 8);
118 msg->l2h = msgb_put(msg, len);
119 memcpy(msg->l2h, data, len);
120
121 msgb_bcid(msg) = msg->l1h;
122 msgb_gmmh(msg) = msg->l2h;
123 return msg;
124}
125
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100126/*
127 * Create a context and search for it
128 */
129static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
130{
131 struct sgsn_mm_ctx *ctx, *ictx;
132 struct gprs_llc_lle *lle;
133 int old_count = count(gprs_llme_list());
134
135 lle = gprs_lle_get_or_create(tlli, 3);
136 ctx = sgsn_mm_ctx_alloc(tlli, raid);
137 ctx->mm_state = GMM_REGISTERED_NORMAL;
138 ctx->llme = lle->llme;
139
140 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
141 OSMO_ASSERT(ictx == ctx);
142
143 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
144
145 return ctx;
146}
147
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100148static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
149 const uint8_t *data, size_t data_len)
150{
151 struct msgb *msg;
152
153 sgsn_tx_counter = 0;
154
155 msg = create_msg(data, data_len);
156 msgb_tlli(msg) = tlli;
157 gsm0408_gprs_rcvmsg(msg, llme);
158 msgb_free(msg);
159}
160
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200161static void test_llme(void)
162{
163 struct gprs_llc_lle *lle, *lle_copy;
164 uint32_t local_tlli;
165 uint32_t foreign_tlli;
166
167 printf("Testing LLME allocations\n");
168 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
169 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
170
171 /* initial state */
172 OSMO_ASSERT(count(gprs_llme_list()) == 0);
173
174 /* Create a new entry */
175 lle = gprs_lle_get_or_create(local_tlli, 3);
176 OSMO_ASSERT(lle);
177 OSMO_ASSERT(count(gprs_llme_list()) == 1);
178
179 /* No new entry is created */
180 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
181 OSMO_ASSERT(lle == lle_copy);
182 OSMO_ASSERT(count(gprs_llme_list()) == 1);
183 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
184 OSMO_ASSERT(lle == lle_copy);
185 OSMO_ASSERT(count(gprs_llme_list()) == 1);
186
187 /* unassign which should delete it*/
188 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
189
190 /* Check that everything was cleaned up */
191 OSMO_ASSERT(count(gprs_llme_list()) == 0);
192}
193
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100194struct gsm_subscriber *last_updated_subscr = NULL;
195void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx,
196 struct gsm_subscriber *subscr)
197{
198 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
199 __func__, mmctx, subscr);
200 last_updated_subscr = subscr;
201}
202
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100203static void assert_subscr(const struct gsm_subscriber *subscr, const char *imsi)
204{
205 struct gsm_subscriber *sfound;
206
207 sfound = gprs_subscr_get_by_imsi(imsi);
208 OSMO_ASSERT(sfound == subscr);
209 subscr_put(sfound);
210
211 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
212}
213
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100214static void show_subscrs(FILE *out)
215{
216 struct gsm_subscriber *subscr;
217
218 llist_for_each_entry(subscr, &active_subscribers, entry) {
219 fprintf(out, " Subscriber: %s, "
220 "use count: %d, keep: %d, timer: %d\n",
221 subscr->imsi, subscr->use_count, subscr->keep_in_ram,
222 osmo_timer_pending(&subscr->sgsn_data->timer));
223 }
224}
225
226static void assert_no_subscrs()
227{
228 show_subscrs(stdout);
229 fflush(stdout);
230 OSMO_ASSERT(llist_empty(&active_subscribers));
231}
232
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100233static void test_subscriber(void)
234{
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100235 struct gsm_subscriber *s1, *s2, *s3, *sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100236 const char *imsi1 = "1234567890";
237 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100238 const char *imsi3 = "5656565656";
239 int saved_expiry_timeout = sgsn->cfg.subscriber_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100240
241 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
242
243 printf("Testing core subscriber data API\n");
244
245 /* Check for emptiness */
246 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
247 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100248 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100249
250 /* Allocate entry 1 */
251 s1 = gprs_subscr_get_or_create(imsi1);
252 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100253 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100254 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100255
256 /* Allocate entry 2 */
257 s2 = gprs_subscr_get_or_create(imsi2);
258 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100259
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100260 /* Allocate entry 3 */
261 s3 = gprs_subscr_get_or_create(imsi3);
262
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100263 /* Check entries */
264 assert_subscr(s1, imsi1);
265 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100266 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100267
268 /* Update entry 1 */
269 last_updated_subscr = NULL;
270 gprs_subscr_update(s1);
271 OSMO_ASSERT(last_updated_subscr == s1);
272
273 /* Because of the update, it won't be freed on delete now */
274 gprs_subscr_delete(s1);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100275 sfound = gprs_subscr_get_by_imsi(imsi1);
276 OSMO_ASSERT(sfound != NULL);
277 s1 = sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100278
279 /* Cancel it, so that delete will free it.
280 * Refcount it to make sure s1 won't be freed here */
281 last_updated_subscr = NULL;
282 gprs_subscr_put_and_cancel(subscr_get(s1));
283 OSMO_ASSERT(last_updated_subscr == s1);
284
285 /* Cancelled entries are still being found */
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100286 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100287
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100288 /* Free entry 1 (GPRS_SUBSCRIBER_CANCELLED is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100289 gprs_subscr_delete(s1);
290 s1 = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100291 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100292 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100293 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100294
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100295 /* Free entry 2 (GSM_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100296 gprs_subscr_delete(s2);
297 s2 = NULL;
298 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
299 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100300 assert_subscr(s3, imsi3);
301
302 /* Try to delete entry 3 */
303 OSMO_ASSERT(sgsn->cfg.subscriber_expiry_timeout == SGSN_TIMEOUT_NEVER);
304 gprs_subscr_delete(s3);
305 assert_subscr(s3, imsi3);
306 /* Process timeouts, this shouldn't delete s3 (SGSN_TIMEOUT_NEVER) */
307 osmo_timers_update();
308 assert_subscr(s3, imsi3);
309 s3 = subscr_get(s3);
310
311 /* Free entry 3 (TIMEOUT == 0) */
312 sgsn->cfg.subscriber_expiry_timeout = 0;
313 gprs_subscr_delete(s3);
314 assert_subscr(s3, imsi3);
315 /* Process timeouts, this should delete s3 */
316 osmo_timers_update();
317 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
318 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
319 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
320 sgsn->cfg.subscriber_expiry_timeout = saved_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100321
322 OSMO_ASSERT(llist_empty(&active_subscribers));
323
324 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
325}
326
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100327static void test_auth_triplets(void)
328{
329 struct gsm_subscriber *s1, *s1found;
330 const char *imsi1 = "1234567890";
331 struct gsm_auth_tuple *at;
332 struct sgsn_mm_ctx *ctx;
333 struct gprs_ra_id raid = { 0, };
334 uint32_t local_tlli = 0xffeeddcc;
335 struct gprs_llc_llme *llme;
336
337 printf("Testing authentication triplet handling\n");
338
339 /* Check for emptiness */
340 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
341
342 /* Allocate entry 1 */
343 s1 = gprs_subscr_get_or_create(imsi1);
344 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
345 s1found = gprs_subscr_get_by_imsi(imsi1);
346 OSMO_ASSERT(s1found == s1);
347 subscr_put(s1found);
348
349 /* Create a context */
350 OSMO_ASSERT(count(gprs_llme_list()) == 0);
351 ctx = alloc_mm_ctx(local_tlli, &raid);
352
353 /* Attach s1 to ctx */
354 ctx->subscr = subscr_get(s1);
355 ctx->subscr->sgsn_data->mm = ctx;
356
357 /* Try to get auth tuple */
358 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
359 OSMO_ASSERT(at == NULL);
360
361 /* Add triplets */
362 s1->sgsn_data->auth_triplets[0].key_seq = 0;
363 s1->sgsn_data->auth_triplets[1].key_seq = 1;
364 s1->sgsn_data->auth_triplets[2].key_seq = 2;
365
366 /* Try to get auth tuple */
367 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
368 OSMO_ASSERT(at != NULL);
369 OSMO_ASSERT(at->key_seq == 0);
370 OSMO_ASSERT(at->use_count == 1);
371 at = sgsn_auth_get_tuple(ctx, at->key_seq);
372 OSMO_ASSERT(at != NULL);
373 OSMO_ASSERT(at->key_seq == 1);
374 OSMO_ASSERT(at->use_count == 1);
375 at = sgsn_auth_get_tuple(ctx, at->key_seq);
376 OSMO_ASSERT(at != NULL);
377 OSMO_ASSERT(at->key_seq == 2);
378 OSMO_ASSERT(at->use_count == 1);
379 at = sgsn_auth_get_tuple(ctx, at->key_seq);
380 OSMO_ASSERT(at == NULL);
381
382 /* Free MM context and subscriber */
383 subscr_put(s1);
384 llme = ctx->llme;
385 sgsn_mm_ctx_free(ctx);
386 s1found = gprs_subscr_get_by_imsi(imsi1);
387 OSMO_ASSERT(s1found == NULL);
388 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
389}
390
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100391#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
392
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100393static int rx_gsup_message(const uint8_t *data, size_t data_len)
394{
395 struct msgb *msg;
396 int rc;
397
398 msg = msgb_alloc(1024, __func__);
399 msg->l2h = msgb_put(msg, data_len);
400 OSMO_ASSERT(msg->l2h != NULL);
401 memcpy(msg->l2h, data, data_len);
402 rc = gprs_subscr_rx_gsup_message(msg);
403 msgb_free(msg);
404
405 return rc;
406}
407
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100408static void test_subscriber_gsup(void)
409{
410 struct gsm_subscriber *s1, *s1found;
411 const char *imsi1 = "1234567890";
412 struct sgsn_mm_ctx *ctx;
413 struct gprs_ra_id raid = { 0, };
414 uint32_t local_tlli = 0xffeeddcc;
415 struct gprs_llc_llme *llme;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100416 int rc;
417
418 static const uint8_t send_auth_info_res[] = {
419 0x0a,
420 TEST_GSUP_IMSI1_IE,
421 0x03, 0x22, /* Auth tuple */
422 0x20, 0x10,
423 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
424 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
425 0x21, 0x04,
426 0x21, 0x22, 0x23, 0x24,
427 0x22, 0x08,
428 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
429 0x03, 0x22, /* Auth tuple */
430 0x20, 0x10,
431 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
432 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
433 0x21, 0x04,
434 0xa1, 0xa2, 0xa3, 0xa4,
435 0x22, 0x08,
436 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
437 };
438
439 static const uint8_t send_auth_info_err[] = {
440 0x09,
441 TEST_GSUP_IMSI1_IE,
442 0x02, 0x01, 0x07 /* GPRS not allowed */
443 };
444
445 static const uint8_t update_location_res[] = {
446 0x06,
447 TEST_GSUP_IMSI1_IE,
448 0x04, 0x00, /* PDP info complete */
449 0x05, 0x12,
450 0x10, 0x01, 0x01,
451 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
452 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
453 0x05, 0x11,
454 0x10, 0x01, 0x02,
455 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
456 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
457 };
458
459 static const uint8_t update_location_err[] = {
460 0x05,
461 TEST_GSUP_IMSI1_IE,
462 0x02, 0x01, 0x07 /* GPRS not allowed */
463 };
464
465 static const uint8_t location_cancellation_req[] = {
466 0x1c,
467 TEST_GSUP_IMSI1_IE,
468 0x06, 0x01, 0x00,
469 };
470
471 printf("Testing subcriber GSUP handling\n");
472
473 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
474
475 /* Check for emptiness */
476 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
477
478 /* Allocate entry 1 */
479 s1 = gprs_subscr_get_or_create(imsi1);
480 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
481 s1found = gprs_subscr_get_by_imsi(imsi1);
482 OSMO_ASSERT(s1found == s1);
483 subscr_put(s1found);
484
485 /* Create a context */
486 OSMO_ASSERT(count(gprs_llme_list()) == 0);
487 ctx = alloc_mm_ctx(local_tlli, &raid);
488 llme = ctx->llme;
489
490 /* Attach s1 to ctx */
491 ctx->subscr = subscr_get(s1);
492 ctx->subscr->sgsn_data->mm = ctx;
493
494 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100495 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100496 OSMO_ASSERT(rc >= 0);
497 OSMO_ASSERT(last_updated_subscr == s1);
498
499 /* Check triplets */
500 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
501 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
502 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
503
504 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100505 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100506 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100507 OSMO_ASSERT(last_updated_subscr == s1);
508
509 /* Check triplets */
510 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
511 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
512 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
513
514 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100515 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100516 OSMO_ASSERT(rc >= 0);
517 OSMO_ASSERT(last_updated_subscr == s1);
518
519 /* Check authorization */
520 OSMO_ASSERT(s1->authorized == 1);
521
522 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100523 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100524 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100525 OSMO_ASSERT(last_updated_subscr == s1);
526
527 /* Check authorization */
528 OSMO_ASSERT(s1->authorized == 0);
529
530 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100531 rc = rx_gsup_message(location_cancellation_req,
532 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100533 OSMO_ASSERT(rc >= 0);
534 OSMO_ASSERT(last_updated_subscr == s1);
535
536 /* Check cancellation result */
537 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
538 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
539
540 /* Free MM context and subscriber */
541 subscr_put(s1);
542 s1found = gprs_subscr_get_by_imsi(imsi1);
543 OSMO_ASSERT(s1found == NULL);
544 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
545
546 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
547}
548
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200549/*
550 * Test that a GMM Detach will remove the MMCTX and the
551 * associated LLME.
552 */
553static void test_gmm_detach(void)
554{
555 struct gprs_ra_id raid = { 0, };
556 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200557 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200558
559 printf("Testing GMM detach\n");
560
561 /* DTAP - Detach Request (MO) */
562 /* normal detach, power_off = 0 */
563 static const unsigned char detach_req[] = {
564 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
565 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
566 };
567
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200568 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200569
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100570 /* Create a context */
571 OSMO_ASSERT(count(gprs_llme_list()) == 0);
572 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200573
574 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100575 send_0408_message(ctx->llme, local_tlli,
576 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200577
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100578 /* verify that a single message (hopefully the Detach Accept) has been
579 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100580 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100581
582 /* verify that things are gone */
583 OSMO_ASSERT(count(gprs_llme_list()) == 0);
584 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
585 OSMO_ASSERT(!ictx);
586}
587
588/*
589 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
590 * will not sent a Detach Accept message (power_off = 1)
591 */
592static void test_gmm_detach_power_off(void)
593{
594 struct gprs_ra_id raid = { 0, };
595 struct sgsn_mm_ctx *ctx, *ictx;
596 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100597
598 printf("Testing GMM detach (power off)\n");
599
600 /* DTAP - Detach Request (MO) */
601 /* normal detach, power_off = 1 */
602 static const unsigned char detach_req[] = {
603 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
604 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
605 };
606
607 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
608
609 /* Create a context */
610 OSMO_ASSERT(count(gprs_llme_list()) == 0);
611 ctx = alloc_mm_ctx(local_tlli, &raid);
612
613 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100614 send_0408_message(ctx->llme, local_tlli,
615 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100616
617 /* verify that no message (and therefore no Detach Accept) has been
618 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100619 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100620
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200621 /* verify that things are gone */
622 OSMO_ASSERT(count(gprs_llme_list()) == 0);
623 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200624 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200625}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200626
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200627/*
628 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
629 */
630static void test_gmm_detach_no_mmctx(void)
631{
632 struct gprs_llc_lle *lle;
633 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200634
635 printf("Testing GMM detach (no MMCTX)\n");
636
637 /* DTAP - Detach Request (MO) */
638 /* normal detach, power_off = 0 */
639 static const unsigned char detach_req[] = {
640 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
641 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
642 };
643
644 /* Create an LLME */
645 OSMO_ASSERT(count(gprs_llme_list()) == 0);
646 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
647 lle = gprs_lle_get_or_create(local_tlli, 3);
648
649 OSMO_ASSERT(count(gprs_llme_list()) == 1);
650
651 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100652 send_0408_message(lle->llme, local_tlli,
653 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200654
655 /* verify that the LLME is gone */
656 OSMO_ASSERT(count(gprs_llme_list()) == 0);
657}
658
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100659/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100660 * Test that a single GMM Detach Accept message will not cause the SGSN to send
661 * any message or leave an MM context at the SGSN.
662 */
663static void test_gmm_detach_accept_unexpected(void)
664{
665 struct gprs_llc_lle *lle;
666 uint32_t local_tlli;
667
668 printf("Testing GMM detach accept (unexpected)\n");
669
670 /* DTAP - Detach Accept (MT) */
671 /* normal detach */
672 static const unsigned char detach_acc[] = {
673 0x08, 0x06
674 };
675
676 /* Create an LLME */
677 OSMO_ASSERT(count(gprs_llme_list()) == 0);
678 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
679 lle = gprs_lle_get_or_create(local_tlli, 3);
680
681 /* inject the detach */
682 send_0408_message(lle->llme, local_tlli,
683 detach_acc, ARRAY_SIZE(detach_acc));
684
685 /* verify that no message (and therefore no Status or XID reset) has been
686 * sent by the SGSN */
687 OSMO_ASSERT(sgsn_tx_counter == 0);
688
689 /* verify that things are gone */
690 OSMO_ASSERT(count(gprs_llme_list()) == 0);
691}
692
693/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100694 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
695 */
696static void test_gmm_status_no_mmctx(void)
697{
698 struct gprs_llc_lle *lle;
699 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100700
701 printf("Testing GMM Status (no MMCTX)\n");
702
703 /* DTAP - GMM Status, protocol error */
704 static const unsigned char gmm_status[] = {
705 0x08, 0x20, 0x6f
706 };
707
708 /* Create an LLME */
709 OSMO_ASSERT(count(gprs_llme_list()) == 0);
710 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
711 lle = gprs_lle_get_or_create(local_tlli, 3);
712
713 OSMO_ASSERT(count(gprs_llme_list()) == 1);
714
715 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100716 send_0408_message(lle->llme, local_tlli,
717 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100718
719 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100720 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100721
722 /* verify that the LLME is gone */
723 OSMO_ASSERT(count(gprs_llme_list()) == 0);
724}
725
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100726/*
727 * Test the GMM Attach procedure
728 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100729static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100730{
731 struct gprs_ra_id raid = { 0, };
732 struct sgsn_mm_ctx *ctx = NULL;
733 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100734 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100735 uint32_t foreign_tlli;
736 uint32_t local_tlli = 0;
737 struct gprs_llc_lle *lle;
738
739 /* DTAP - Attach Request */
740 /* The P-TMSI is not known by the SGSN */
741 static const unsigned char attach_req[] = {
742 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
743 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
744 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
745 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
746 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
747 };
748
749 /* DTAP - Identity Response IMEI */
750 static const unsigned char ident_resp_imei[] = {
751 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
752 0x56
753 };
754
755 /* DTAP - Identity Response IMSI */
756 static const unsigned char ident_resp_imsi[] = {
757 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
758 0x54
759 };
760
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100761 /* DTAP - Authentication and Ciphering Resp */
762 static const unsigned char auth_ciph_resp[] = {
763 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
764 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
765 };
766
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100767 /* DTAP - Attach Complete */
768 static const unsigned char attach_compl[] = {
769 0x08, 0x03
770 };
771
772 /* DTAP - Detach Request (MO) */
773 /* normal detach, power_off = 0 */
774 static const unsigned char detach_req[] = {
775 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
776 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
777 };
778
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100779 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100780
781 /* reset the PRNG used by sgsn_alloc_ptmsi */
782 srand(1);
783
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100784 ptmsi1 = sgsn_alloc_ptmsi();
785 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
786
787 /* reset the PRNG, so that the same P-TMSI sequence will be generated
788 * again */
789 srand(1);
790
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100791 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
792
793 /* Create a LLE/LLME */
794 OSMO_ASSERT(count(gprs_llme_list()) == 0);
795 lle = gprs_lle_get_or_create(foreign_tlli, 3);
796 OSMO_ASSERT(count(gprs_llme_list()) == 1);
797
798 /* inject the attach request */
799 send_0408_message(lle->llme, foreign_tlli,
800 attach_req, ARRAY_SIZE(attach_req));
801
802 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
803 OSMO_ASSERT(ctx != NULL);
804 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
805
806 /* we expect an identity request (IMEI) */
807 OSMO_ASSERT(sgsn_tx_counter == 1);
808
809 /* inject the identity response (IMEI) */
810 send_0408_message(ctx->llme, foreign_tlli,
811 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
812
813 /* we expect an identity request (IMSI) */
814 OSMO_ASSERT(sgsn_tx_counter == 1);
815
816 /* inject the identity response (IMSI) */
817 send_0408_message(ctx->llme, foreign_tlli,
818 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
819
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100820 /* check that the MM context has not been removed due to a failed
821 * authorization */
822 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
823
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100824 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100825
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100826retry_attach_req:
827
828 if (retry && sgsn_tx_counter == 0) {
829 fprintf(stderr, "Retrying attach request\n");
830 /* re-inject the attach request */
831 send_0408_message(lle->llme, foreign_tlli,
832 attach_req, ARRAY_SIZE(attach_req));
833 }
834
835 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
836 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100837
838 /* inject the auth & ciph response */
839 send_0408_message(ctx->llme, foreign_tlli,
840 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
841
842 /* check that the MM context has not been removed due to a
843 * failed authorization */
844 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
845 }
846
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100847 if (retry && sgsn_tx_counter == 0)
848 goto retry_attach_req;
849
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100850 /* we expect an attach accept/reject */
851 OSMO_ASSERT(sgsn_tx_counter == 1);
852
853 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100854 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100855
856 /* inject the attach complete */
857 send_0408_message(ctx->llme, local_tlli,
858 attach_compl, ARRAY_SIZE(attach_compl));
859
860 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
861
862 /* we don't expect a response */
863 OSMO_ASSERT(sgsn_tx_counter == 0);
864
865 /* inject the detach */
866 send_0408_message(ctx->llme, local_tlli,
867 detach_req, ARRAY_SIZE(detach_req));
868
869 /* verify that things are gone */
870 OSMO_ASSERT(count(gprs_llme_list()) == 0);
871 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
872 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100873}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100874
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100875static void test_gmm_attach_acl(void)
876{
877 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
878
879 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
880 sgsn_acl_add("123456789012345", &sgsn->cfg);
881 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100882 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100883 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100884
885 sgsn->cfg.auth_policy = saved_auth_policy;
886}
887
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100888int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100889 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100890 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100891 if (rc == -ENOTSUP) {
892 OSMO_ASSERT(mmctx->subscr);
893 gprs_subscr_update(mmctx->subscr);
894 }
895 return rc;
896};
897
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100898int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
899 gprs_subscr_update(mmctx->subscr);
900 return 0;
901};
902
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100903static void cleanup_subscr_by_imsi(const char *imsi)
904{
905 struct gsm_subscriber *subscr;
906
907 subscr = gprs_subscr_get_by_imsi(imsi);
908 OSMO_ASSERT(subscr != NULL);
Jacob Erlbecke1beb6f2015-01-08 14:13:46 +0100909 subscr->keep_in_ram = 0;
910 subscr_put(subscr);
911 subscr = gprs_subscr_get_by_imsi(imsi);
912 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100913}
914
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100915static void test_gmm_attach_subscr(void)
916{
917 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
918 struct gsm_subscriber *subscr;
919
920 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100921 subscr_request_update_location_cb = my_subscr_request_update_location;
922 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100923
924 subscr = gprs_subscr_get_or_create("123456789012345");
925 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100926 subscr->keep_in_ram = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100927 subscr_put(subscr);
928
929 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100930 test_gmm_attach(0);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100931
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100932 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100933 assert_no_subscrs();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100934
935 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100936 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
937 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100938}
939
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100940int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
941{
942 /* Fake an authentication */
943 OSMO_ASSERT(mmctx->subscr);
944 mmctx->is_authenticated = 1;
945 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100946
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100947 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100948};
949
950static void test_gmm_attach_subscr_fake_auth(void)
951{
952 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
953 struct gsm_subscriber *subscr;
954
955 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100956 subscr_request_update_location_cb = my_subscr_request_update_location;
957 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100958
959 subscr = gprs_subscr_get_or_create("123456789012345");
960 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100961 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100962 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100963 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100964 subscr_put(subscr);
965
966 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100967 test_gmm_attach(0);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100968
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100969 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100970 assert_no_subscrs();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100971
972 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100973 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
974 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
975}
976
977int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
978{
979 struct gsm_auth_tuple at = {
980 .sres = {0x51, 0xe5, 0x51, 0xe5},
981 .key_seq = 0
982 };
983
984 /* Fake an authentication */
985 OSMO_ASSERT(mmctx->subscr);
986 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
987
988 gprs_subscr_update_auth_info(mmctx->subscr);
989
990 return 0;
991};
992
993static void test_gmm_attach_subscr_real_auth(void)
994{
995 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
996 struct gsm_subscriber *subscr;
997
998 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
999 subscr_request_update_location_cb = my_subscr_request_update_location;
1000 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
1001
1002 subscr = gprs_subscr_get_or_create("123456789012345");
1003 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +01001004 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001005 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001006 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001007 subscr_put(subscr);
1008
1009 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001010
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001011 test_gmm_attach(0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001012
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +01001013 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001014 assert_no_subscrs();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001015
1016 sgsn->cfg.auth_policy = saved_auth_policy;
1017 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1018 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001019}
1020
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001021#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
1022 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
1023
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001024static int auth_info_skip = 0;
1025static int upd_loc_skip = 0;
1026
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001027int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
1028{
1029 static const uint8_t send_auth_info_res[] = {
1030 0x0a,
1031 TEST_GSUP_IMSI_LONG_IE,
1032 0x03, 0x22, /* Auth tuple */
1033 0x20, 0x10,
1034 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1035 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1036 0x21, 0x04,
1037 0x51, 0xe5, 0x51, 0xe5,
1038 0x22, 0x08,
1039 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1040 };
1041
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001042 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001043
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001044 if (auth_info_skip > 0) {
1045 auth_info_skip -= 1;
1046 return -EAGAIN;
1047 }
1048
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001049 /* Fake an SendAuthInfoRes */
1050 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1051
1052 return 0;
1053};
1054
1055int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1056 static const uint8_t update_location_res[] = {
1057 0x06,
1058 TEST_GSUP_IMSI_LONG_IE,
1059 0x04, 0x00, /* PDP info complete */
1060 0x05, 0x12,
1061 0x10, 0x01, 0x01,
1062 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1063 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
1064 };
1065
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001066 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001067
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001068 if (upd_loc_skip > 0) {
1069 upd_loc_skip -= 1;
1070 return -EAGAIN;
1071 }
1072
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001073 /* Fake an UpdateLocRes */
1074 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1075};
1076
1077
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001078static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001079{
1080 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1081 struct gsm_subscriber *subscr;
1082
1083 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1084 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1085 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001086 if (retry) {
1087 upd_loc_skip = 3;
1088 auth_info_skip = 3;
1089 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001090
1091 subscr = gprs_subscr_get_or_create("123456789012345");
1092 subscr->authorized = 1;
1093 sgsn->cfg.require_authentication = 1;
1094 sgsn->cfg.require_update_location = 1;
1095 subscr_put(subscr);
1096
1097 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001098 test_gmm_attach(retry);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001099
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001100 cleanup_subscr_by_imsi("123456789012345");
1101 assert_no_subscrs();
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001102
1103 sgsn->cfg.auth_policy = saved_auth_policy;
1104 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1105 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001106 upd_loc_skip = 0;
1107 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001108}
1109
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001110int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1111{
1112 struct gprs_gsup_message to_peer;
1113 struct gprs_gsup_message from_peer;
1114 struct msgb *reply_msg;
1115
1116 /* Simulate the GSUP peer */
1117 gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1118
1119 /* This invalidates the pointers in to_peer */
1120 msgb_free(msg);
1121
1122 switch (to_peer.message_type) {
1123 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1124 /* Send UPDATE_LOCATION_RESULT */
1125 return my_subscr_request_update_gsup_auth(NULL);
1126
1127 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1128 /* Send SEND_AUTH_INFO_RESULT */
1129 return my_subscr_request_auth_info_gsup_auth(NULL);
1130
1131 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
1132 /* TODO: send RES/ERR */
1133 return 0;
1134
1135 default:
1136 if ((to_peer.message_type & 0b00000011) == 0) {
1137 /* Unhandled request */
1138 /* TODO: send error(NOT_IMPL) */
1139 from_peer.message_type = to_peer.message_type + 1;
1140 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1141 break;
1142 }
1143
1144 /* Ignore it */
1145 return 0;
1146 }
1147
1148 reply_msg = gprs_gsup_msgb_alloc();
1149 reply_msg->l2h = reply_msg->data;
1150 gprs_gsup_encode(reply_msg, &from_peer);
1151 gprs_subscr_rx_gsup_message(reply_msg);
1152 msgb_free(reply_msg);
1153
1154 return 0;
1155};
1156
1157static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1158{
1159 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1160 struct gsm_subscriber *subscr;
1161
1162 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1163 sgsn_inst.cfg.subscriber_expiry_timeout = 0;
1164 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1165
1166 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1167
1168 if (retry) {
1169 upd_loc_skip = 3;
1170 auth_info_skip = 3;
1171 }
1172
1173 printf("Auth policy 'remote', real GSUP based auth: ");
1174 test_gmm_attach(retry);
1175
1176 subscr = gprs_subscr_get_by_imsi("123456789012345");
1177 OSMO_ASSERT(subscr != NULL);
1178 gprs_subscr_delete(subscr);
1179
1180 osmo_timers_update();
1181
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001182 assert_no_subscrs();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001183
1184 sgsn->cfg.auth_policy = saved_auth_policy;
1185 sgsn_inst.cfg.subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER;
1186 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1187 upd_loc_skip = 0;
1188 auth_info_skip = 0;
1189 talloc_free(sgsn->gsup_client);
1190 sgsn->gsup_client = NULL;
1191}
1192
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001193/*
1194 * Test the GMM Rejects
1195 */
1196static void test_gmm_reject(void)
1197{
1198 struct gprs_ra_id raid = { 0, };
1199 struct sgsn_mm_ctx *ctx = NULL;
1200 uint32_t foreign_tlli;
1201 struct gprs_llc_lle *lle;
1202 int idx;
1203
1204 /* DTAP - Attach Request */
1205 /* Invalid MI length */
1206 static const unsigned char attach_req_inv_mi_len[] = {
1207 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1208 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1209 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1210 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1211 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1212 };
1213
1214 /* DTAP - Attach Request */
1215 /* Invalid MI type (IMEI) */
1216 static const unsigned char attach_req_inv_mi_type[] = {
1217 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1218 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1219 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1220 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1221 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1222 };
1223
1224 /* DTAP - Routing Area Update Request */
1225 static const unsigned char dtap_ra_upd_req[] = {
1226 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1227 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1228 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1229 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1230 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1231 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1232 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1233 };
1234
1235 /* DTAP - Routing Area Update Request */
1236 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1237 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1238 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1239 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1240 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1241 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1242 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1243 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1244 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1245 };
1246
1247 /* DTAP - Routing Area Update Request */
1248 /* Invalid cap length */
1249 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1250 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1251 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1252 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1253 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1254 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1255 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1256 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1257 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1258 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1259 };
1260
1261 struct test {
1262 const char *title;
1263 const unsigned char *msg;
1264 unsigned msg_len;
1265 unsigned num_resp;
1266
1267 };
1268 static struct test tests[] = {
1269 {
1270 .title = "Attach Request (invalid MI length)",
1271 .msg = attach_req_inv_mi_len,
1272 .msg_len = sizeof(attach_req_inv_mi_len),
1273 .num_resp = 1 /* Reject */
1274
1275 },
1276 {
1277 .title = "Attach Request (invalid MI type)",
1278 .msg = attach_req_inv_mi_type,
1279 .msg_len = sizeof(attach_req_inv_mi_type),
1280 .num_resp = 1 /* Reject */
1281 },
1282 {
1283 .title = "Routing Area Update Request (valid)",
1284 .msg = dtap_ra_upd_req,
1285 .msg_len = sizeof(dtap_ra_upd_req),
1286 .num_resp = 2 /* XID Reset + Reject */
1287 },
1288 {
1289 .title = "Routing Area Update Request (invalid type)",
1290 .msg = dtap_ra_upd_req_inv_type,
1291 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1292 .num_resp = 1 /* Reject */
1293 },
1294 {
1295 .title = "Routing Area Update Request (invalid CAP length)",
1296 .msg = dtap_ra_upd_req_inv_cap_len,
1297 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1298 .num_resp = 1 /* Reject */
1299 },
1300 };
1301
1302 printf("Testing GMM reject\n");
1303
1304 /* reset the PRNG used by sgsn_alloc_ptmsi */
1305 srand(1);
1306
1307 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1308
1309 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1310
1311 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1312 const struct test *test = &tests[idx];
1313 printf(" - %s\n", test->title);
1314
1315 /* Create a LLE/LLME */
1316 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1317 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1318
1319 /* Inject the Request message */
1320 send_0408_message(lle->llme, foreign_tlli,
1321 test->msg, test->msg_len);
1322
1323 /* We expect a Reject message */
1324 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1325 sgsn_tx_counter, test->num_resp);
1326 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1327
1328 /* verify that LLME/MM are removed */
1329 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1330 OSMO_ASSERT(ctx == NULL);
1331 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1332 }
1333}
1334
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001335/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001336 * Test cancellation of attached MM contexts
1337 */
1338static void test_gmm_cancel(void)
1339{
1340 struct gprs_ra_id raid = { 0, };
1341 struct sgsn_mm_ctx *ctx = NULL;
1342 struct sgsn_mm_ctx *ictx;
1343 uint32_t ptmsi1;
1344 uint32_t foreign_tlli;
1345 uint32_t local_tlli = 0;
1346 struct gprs_llc_lle *lle;
1347 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1348
1349 /* DTAP - Attach Request */
1350 /* The P-TMSI is not known by the SGSN */
1351 static const unsigned char attach_req[] = {
1352 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1353 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1354 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1355 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1356 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1357 };
1358
1359 /* DTAP - Identity Response IMEI */
1360 static const unsigned char ident_resp_imei[] = {
1361 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1362 0x56
1363 };
1364
1365 /* DTAP - Identity Response IMSI */
1366 static const unsigned char ident_resp_imsi[] = {
1367 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1368 0x54
1369 };
1370
1371 /* DTAP - Attach Complete */
1372 static const unsigned char attach_compl[] = {
1373 0x08, 0x03
1374 };
1375
1376 printf("Testing cancellation\n");
1377
1378 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1379
1380 /* reset the PRNG used by sgsn_alloc_ptmsi */
1381 srand(1);
1382
1383 ptmsi1 = sgsn_alloc_ptmsi();
1384 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1385
1386 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1387 * again */
1388 srand(1);
1389
1390 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1391
1392 /* Create a LLE/LLME */
1393 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1394 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1395 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1396
1397 /* inject the attach request */
1398 send_0408_message(lle->llme, foreign_tlli,
1399 attach_req, ARRAY_SIZE(attach_req));
1400
1401 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1402 OSMO_ASSERT(ctx != NULL);
1403 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1404
1405 /* we expect an identity request (IMEI) */
1406 OSMO_ASSERT(sgsn_tx_counter == 1);
1407
1408 /* inject the identity response (IMEI) */
1409 send_0408_message(ctx->llme, foreign_tlli,
1410 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1411
1412 /* we expect an identity request (IMSI) */
1413 OSMO_ASSERT(sgsn_tx_counter == 1);
1414
1415 /* inject the identity response (IMSI) */
1416 send_0408_message(ctx->llme, foreign_tlli,
1417 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1418
1419 /* check that the MM context has not been removed due to a failed
1420 * authorization */
1421 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1422
1423 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1424
1425 /* we expect an attach accept/reject */
1426 OSMO_ASSERT(sgsn_tx_counter == 1);
1427
1428 /* this has been randomly assigned by the SGSN */
1429 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1430
1431 /* inject the attach complete */
1432 send_0408_message(ctx->llme, local_tlli,
1433 attach_compl, ARRAY_SIZE(attach_compl));
1434
1435 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1436
1437 /* we don't expect a response */
1438 OSMO_ASSERT(sgsn_tx_counter == 0);
1439
1440 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001441 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001442
1443 /* verify that things are gone */
1444 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1445 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1446 OSMO_ASSERT(!ictx);
1447
1448 sgsn->cfg.auth_policy = saved_auth_policy;
1449}
1450
1451/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001452 * Test the dynamic allocation of P-TMSIs
1453 */
1454static void test_gmm_ptmsi_allocation(void)
1455{
1456 struct gprs_ra_id raid = { 0, };
1457 struct sgsn_mm_ctx *ctx = NULL;
1458 struct sgsn_mm_ctx *ictx;
1459 uint32_t foreign_tlli;
1460 uint32_t ptmsi1;
1461 uint32_t ptmsi2;
1462 uint32_t old_ptmsi;
1463 uint32_t local_tlli = 0;
1464 struct gprs_llc_lle *lle;
1465 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1466
1467 /* DTAP - Attach Request (IMSI 12131415161718) */
1468 static const unsigned char attach_req[] = {
1469 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1470 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1471 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1472 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1473 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1474 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1475 0x00,
1476 };
1477
1478 /* DTAP - Identity Response IMEI */
1479 static const unsigned char ident_resp_imei[] = {
1480 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1481 0x56
1482 };
1483
1484 /* DTAP - Attach Complete */
1485 static const unsigned char attach_compl[] = {
1486 0x08, 0x03
1487 };
1488
1489 /* DTAP - Routing Area Update Request */
1490 static const unsigned char ra_upd_req[] = {
1491 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1492 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1493 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1494 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1495 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1496 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1497 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1498 };
1499
1500 /* DTAP - Routing Area Update Complete */
1501 static const unsigned char ra_upd_complete[] = {
1502 0x08, 0x0a
1503 };
1504
1505 /* DTAP - Detach Request (MO) */
1506 /* normal detach, power_off = 1 */
1507 static const unsigned char detach_req[] = {
1508 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1509 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1510 };
1511
1512 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1513
1514 printf("Testing P-TMSI allocation\n");
1515
1516 printf(" - sgsn_alloc_ptmsi\n");
1517
1518 /* reset the PRNG used by sgsn_alloc_ptmsi */
1519 srand(1);
1520
1521 ptmsi1 = sgsn_alloc_ptmsi();
1522 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1523
1524 ptmsi2 = sgsn_alloc_ptmsi();
1525 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1526
1527 OSMO_ASSERT(ptmsi1 != ptmsi2);
1528
1529 printf(" - Repeated Attach Request\n");
1530
1531 /* reset the PRNG, so that the same P-TMSI will be generated
1532 * again */
1533 srand(1);
1534
1535 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1536
1537 /* Create a LLE/LLME */
1538 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1539 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1540 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1541
1542 /* inject the attach request */
1543 send_0408_message(lle->llme, foreign_tlli,
1544 attach_req, ARRAY_SIZE(attach_req));
1545
1546 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1547 OSMO_ASSERT(ctx != NULL);
1548 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1549 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1550
1551 old_ptmsi = ctx->p_tmsi_old;
1552
1553 /* we expect an identity request (IMEI) */
1554 OSMO_ASSERT(sgsn_tx_counter == 1);
1555
1556 /* inject the identity response (IMEI) */
1557 send_0408_message(ctx->llme, foreign_tlli,
1558 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1559
1560 /* check that the MM context has not been removed due to a failed
1561 * authorization */
1562 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1563
1564 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1565 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1566
1567 /* we expect an attach accept */
1568 OSMO_ASSERT(sgsn_tx_counter == 1);
1569
1570 /* we ignore this and send the attach again */
1571 send_0408_message(lle->llme, foreign_tlli,
1572 attach_req, ARRAY_SIZE(attach_req));
1573
1574 /* the allocated P-TMSI should be the same */
1575 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1576 OSMO_ASSERT(ctx != NULL);
1577 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1578 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1579 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1580
1581 /* inject the attach complete */
1582 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1583 send_0408_message(ctx->llme, local_tlli,
1584 attach_compl, ARRAY_SIZE(attach_compl));
1585
1586 /* we don't expect a response */
1587 OSMO_ASSERT(sgsn_tx_counter == 0);
1588
1589 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1590 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1591 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1592
1593 printf(" - Repeated RA Update Request\n");
1594
1595 /* inject the RA update request */
1596 send_0408_message(ctx->llme, local_tlli,
1597 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1598
1599 /* we expect an RA update accept */
1600 OSMO_ASSERT(sgsn_tx_counter == 1);
1601
1602 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1603 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1604 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1605
1606 /* repeat the RA update request */
1607 send_0408_message(ctx->llme, local_tlli,
1608 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1609
1610 /* we expect an RA update accept */
1611 OSMO_ASSERT(sgsn_tx_counter == 1);
1612
1613 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1614 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1615 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1616
1617 /* inject the RA update complete */
1618 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1619 send_0408_message(ctx->llme, local_tlli,
1620 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1621
1622 /* we don't expect a response */
1623 OSMO_ASSERT(sgsn_tx_counter == 0);
1624
1625 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1626 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1627 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1628
1629 /* inject the detach */
1630 send_0408_message(ctx->llme, local_tlli,
1631 detach_req, ARRAY_SIZE(detach_req));
1632
1633 /* verify that things are gone */
1634 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1635 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1636 OSMO_ASSERT(!ictx);
1637
1638 sgsn->cfg.auth_policy = saved_auth_policy;
1639}
1640
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001641static struct log_info_cat gprs_categories[] = {
1642 [DMM] = {
1643 .name = "DMM",
1644 .description = "Layer3 Mobility Management (MM)",
1645 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001646 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001647 },
1648 [DPAG] = {
1649 .name = "DPAG",
1650 .description = "Paging Subsystem",
1651 .color = "\033[1;38m",
1652 .enabled = 1, .loglevel = LOGL_NOTICE,
1653 },
1654 [DMEAS] = {
1655 .name = "DMEAS",
1656 .description = "Radio Measurement Processing",
1657 .enabled = 0, .loglevel = LOGL_NOTICE,
1658 },
1659 [DREF] = {
1660 .name = "DREF",
1661 .description = "Reference Counting",
1662 .enabled = 0, .loglevel = LOGL_NOTICE,
1663 },
1664 [DGPRS] = {
1665 .name = "DGPRS",
1666 .description = "GPRS Packet Service",
1667 .enabled = 1, .loglevel = LOGL_DEBUG,
1668 },
1669 [DNS] = {
1670 .name = "DNS",
1671 .description = "GPRS Network Service (NS)",
1672 .enabled = 1, .loglevel = LOGL_INFO,
1673 },
1674 [DBSSGP] = {
1675 .name = "DBSSGP",
1676 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1677 .enabled = 1, .loglevel = LOGL_DEBUG,
1678 },
1679 [DLLC] = {
1680 .name = "DLLC",
1681 .description = "GPRS Logical Link Control Protocol (LLC)",
1682 .enabled = 1, .loglevel = LOGL_DEBUG,
1683 },
1684 [DSNDCP] = {
1685 .name = "DSNDCP",
1686 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1687 .enabled = 1, .loglevel = LOGL_DEBUG,
1688 },
1689};
1690
1691static struct log_info info = {
1692 .cat = gprs_categories,
1693 .num_cat = ARRAY_SIZE(gprs_categories),
1694};
1695
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001696int main(int argc, char **argv)
1697{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001698 osmo_init_logging(&info);
1699 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1700 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1701
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001702 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001703 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001704
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001705 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001706 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001707 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001708 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001709 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001710 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001711 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001712 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001713 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001714 test_gmm_attach_acl();
1715 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001716 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001717 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001718 test_gmm_attach_subscr_gsup_auth(0);
1719 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001720 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001721 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001722 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001723 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001724 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001725
1726 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01001727 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001728 return 0;
1729}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001730
1731
1732/* stubs */
1733struct osmo_prim_hdr;
1734int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1735{
1736 abort();
1737}