blob: 818106190b308f2079d4f860c799c489fb5c1229 [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>
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +010027#include <openbsc/gprs_gsup_messages.h>
28#include <openbsc/gprs_gsup_client.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020029
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010030#include <osmocom/gprs/gprs_bssgp.h>
31
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020032#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeck092bbc82015-01-05 18:57:32 +010033#include <openbsc/gsm_04_08_gprs.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020034
35#include <osmocom/core/application.h>
36#include <osmocom/core/msgb.h>
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010037#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020038
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +020039#include <stdio.h>
40
Holger Hans Peter Freyther49dbcd92014-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 Erlbeckd7b77732014-11-04 10:08:37 +010048 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +010049 .subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020050 },
51};
52struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck0b2da872014-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 Erlbeck6e6b3302015-01-13 11:56:28 +010060 msgb_free(msg);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010061 return 0;
62}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020063
Jacob Erlbecke8b69682014-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 Erlbeck828059f2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +010079
Jacob Erlbeck828059f2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +010091};
Jacob Erlbecke8b69682014-11-12 10:12:11 +010092
Jacob Erlbeck0d2cf602015-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 Freyther49dbcd92014-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 Freyther94246842014-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 Erlbeckf43a2992014-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 Erlbeck75488292014-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 Freyther49dbcd92014-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 Erlbecke8b69682014-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 Erlbecka695d242015-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 Erlbeck8768f2b2015-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 Erlbecke8b69682014-11-12 10:12:11 +0100233static void test_subscriber(void)
234{
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100235 struct gsm_subscriber *s1, *s2, *s3, *sfound;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100236 const char *imsi1 = "1234567890";
237 const char *imsi2 = "9876543210";
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100238 const char *imsi3 = "5656565656";
239 int saved_expiry_timeout = sgsn->cfg.subscriber_expiry_timeout;
Jacob Erlbecke8b69682014-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 Erlbeck9bf4be92015-01-06 16:32:41 +0100248 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbecke8b69682014-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 Erlbecka695d242015-01-09 11:59:50 +0100253 assert_subscr(s1, imsi1);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100254 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbecke8b69682014-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 Erlbecka695d242015-01-09 11:59:50 +0100259
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100260 /* Allocate entry 3 */
261 s3 = gprs_subscr_get_or_create(imsi3);
262
Jacob Erlbecka695d242015-01-09 11:59:50 +0100263 /* Check entries */
264 assert_subscr(s1, imsi1);
265 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100266 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-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 Erlbecka695d242015-01-09 11:59:50 +0100275 sfound = gprs_subscr_get_by_imsi(imsi1);
276 OSMO_ASSERT(sfound != NULL);
277 s1 = sfound;
Jacob Erlbecke8b69682014-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 Erlbecka695d242015-01-09 11:59:50 +0100286 assert_subscr(s1, imsi1);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100287
Jacob Erlbecka695d242015-01-09 11:59:50 +0100288 /* Free entry 1 (GPRS_SUBSCRIBER_CANCELLED is set) */
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100289 gprs_subscr_delete(s1);
290 s1 = NULL;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100291 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100292 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100293 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100294
Jacob Erlbecka695d242015-01-09 11:59:50 +0100295 /* Free entry 2 (GSM_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbecke8b69682014-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 Erlbeck9bf4be92015-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 Erlbecke8b69682014-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 Erlbeckb1332b62014-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 Erlbeck5641cfc2014-12-12 15:01:37 +0100391#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
392
Jacob Erlbeckb5c51432014-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 Erlbeck5641cfc2014-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 Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100495 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100505 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100506 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100515 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100523 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100524 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-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 Erlbeckb5c51432014-12-19 18:19:50 +0100531 rc = rx_gsup_message(location_cancellation_req,
532 sizeof(location_cancellation_req));
Jacob Erlbeck5641cfc2014-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 Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200557 uint32_t local_tlli;
Holger Hans Peter Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200568 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200569
Jacob Erlbeckf43a2992014-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 Freyther94246842014-10-02 22:24:47 +0200573
574 /* inject the detach */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100575 send_0408_message(ctx->llme, local_tlli,
576 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200577
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100578 /* verify that a single message (hopefully the Detach Accept) has been
579 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100580 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck0b2da872014-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 Erlbeck0b2da872014-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 Erlbeck75488292014-10-29 10:31:18 +0100614 send_0408_message(ctx->llme, local_tlli,
615 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100616
617 /* verify that no message (and therefore no Detach Accept) has been
618 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100619 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100620
Holger Hans Peter Freyther94246842014-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 Erlbeck12396bd2014-09-30 13:51:45 +0200624 OSMO_ASSERT(!ictx);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200625}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200626
Jacob Erlbeck42d284f2014-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 Erlbeck42d284f2014-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 Erlbeck75488292014-10-29 10:31:18 +0100652 send_0408_message(lle->llme, local_tlli,
653 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200654
655 /* verify that the LLME is gone */
656 OSMO_ASSERT(count(gprs_llme_list()) == 0);
657}
658
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100659/*
Jacob Erlbeck021a0d12014-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 Erlbeckb35ee6b2014-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 Erlbeckb35ee6b2014-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 Erlbeck75488292014-10-29 10:31:18 +0100716 send_0408_message(lle->llme, local_tlli,
717 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100718
719 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100720 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100721
722 /* verify that the LLME is gone */
723 OSMO_ASSERT(count(gprs_llme_list()) == 0);
724}
725
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100726/*
727 * Test the GMM Attach procedure
728 */
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100729static void test_gmm_attach(int retry)
Jacob Erlbeck7c24b3e2014-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 Erlbeck0a2c7912014-11-24 14:40:28 +0100734 uint32_t ptmsi1;
Jacob Erlbeck7c24b3e2014-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 Erlbeck828059f2014-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 Erlbeck7c24b3e2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100779 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100780
781 /* reset the PRNG used by sgsn_alloc_ptmsi */
782 srand(1);
783
Jacob Erlbeck0a2c7912014-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 Erlbeck7c24b3e2014-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 Erlbeck7c24b3e2014-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 Erlbeck67318ef2014-10-28 16:23:46 +0100824 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100825
Jacob Erlbeck803ebfa2014-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 Erlbeck828059f2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100847 if (retry && sgsn_tx_counter == 0)
848 goto retry_attach_req;
849
Jacob Erlbeck7c24b3e2014-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 Erlbeck0a2c7912014-11-24 14:40:28 +0100854 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck7c24b3e2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +0100873}
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100874
Jacob Erlbeckd04f7cc2014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100882 test_gmm_attach(0);
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100883 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100884
885 sgsn->cfg.auth_policy = saved_auth_policy;
886}
887
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100888int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100889 int rc;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100890 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckd04f7cc2014-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 Erlbeck828059f2014-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 Erlbeck03386f62015-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 Erlbeckdc7e8b92015-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 Erlbeck03386f62015-01-08 14:08:16 +0100913}
914
Jacob Erlbeckd04f7cc2014-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 Erlbeck828059f2014-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 Erlbeckd04f7cc2014-11-12 10:18:09 +0100923
924 subscr = gprs_subscr_get_or_create("123456789012345");
925 subscr->authorized = 1;
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100926 subscr->keep_in_ram = 1;
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100927 subscr_put(subscr);
928
929 printf("Auth policy 'remote': ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100930 test_gmm_attach(0);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100931
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100932 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100933 assert_no_subscrs();
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100934
935 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck828059f2014-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 Erlbeck7c24b3e2014-10-29 12:11:58 +0100938}
939
Jacob Erlbeck828059f2014-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 Erlbeckd8126992014-12-08 15:26:47 +0100946
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100947 return 0;
Jacob Erlbeckd8126992014-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 Erlbeck828059f2014-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 Erlbeckd8126992014-12-08 15:26:47 +0100958
959 subscr = gprs_subscr_get_or_create("123456789012345");
960 subscr->authorized = 1;
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100961 subscr->keep_in_ram = 1;
Jacob Erlbeck16b17ed2014-12-17 13:20:08 +0100962 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck6ff7f642014-12-19 18:08:48 +0100963 sgsn->cfg.require_update_location = 1;
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100964 subscr_put(subscr);
965
966 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100967 test_gmm_attach(0);
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100968
Jacob Erlbeck03386f62015-01-08 14:08:16 +0100969 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100970 assert_no_subscrs();
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100971
972 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck828059f2014-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 Erlbeck9bf4be92015-01-06 16:32:41 +01001004 subscr->keep_in_ram = 1;
Jacob Erlbeck16b17ed2014-12-17 13:20:08 +01001005 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck6ff7f642014-12-19 18:08:48 +01001006 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck828059f2014-11-28 14:55:25 +01001007 subscr_put(subscr);
1008
1009 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +01001010
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001011 test_gmm_attach(0);
Jacob Erlbeck828059f2014-11-28 14:55:25 +01001012
Jacob Erlbeck03386f62015-01-08 14:08:16 +01001013 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +01001014 assert_no_subscrs();
Jacob Erlbeck828059f2014-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 Erlbeckd8126992014-12-08 15:26:47 +01001019}
1020
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +01001024static int auth_info_skip = 0;
1025static int upd_loc_skip = 0;
1026
Jacob Erlbeckdebbdd72014-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 Erlbeck0d2cf602015-01-09 15:07:16 +01001042 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001043
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001044 if (auth_info_skip > 0) {
1045 auth_info_skip -= 1;
1046 return -EAGAIN;
1047 }
1048
Jacob Erlbeckdebbdd72014-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 Erlbeck0d2cf602015-01-09 15:07:16 +01001066 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001067
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001068 if (upd_loc_skip > 0) {
1069 upd_loc_skip -= 1;
1070 return -EAGAIN;
1071 }
1072
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +01001078static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +01001086 if (retry) {
1087 upd_loc_skip = 3;
1088 auth_info_skip = 3;
1089 }
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +01001098 test_gmm_attach(retry);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001099
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +01001100 cleanup_subscr_by_imsi("123456789012345");
1101 assert_no_subscrs();
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +01001106 upd_loc_skip = 0;
1107 auth_info_skip = 0;
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001108}
1109
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001110int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1111{
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001112 struct gprs_gsup_message to_peer = {0};
1113 struct gprs_gsup_message from_peer = {0};
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001114 struct msgb *reply_msg;
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001115 int rc;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001116
1117 /* Simulate the GSUP peer */
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001118 rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1119 OSMO_ASSERT(rc >= 0);
1120 OSMO_ASSERT(to_peer.imsi[0] != 0);
1121 strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001122
1123 /* This invalidates the pointers in to_peer */
1124 msgb_free(msg);
1125
1126 switch (to_peer.message_type) {
1127 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1128 /* Send UPDATE_LOCATION_RESULT */
1129 return my_subscr_request_update_gsup_auth(NULL);
1130
1131 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1132 /* Send SEND_AUTH_INFO_RESULT */
1133 return my_subscr_request_auth_info_gsup_auth(NULL);
1134
1135 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001136 from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
1137 break;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001138
1139 default:
1140 if ((to_peer.message_type & 0b00000011) == 0) {
1141 /* Unhandled request */
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001142 /* Send error(NOT_IMPL) */
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001143 from_peer.message_type = to_peer.message_type + 1;
1144 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1145 break;
1146 }
1147
1148 /* Ignore it */
1149 return 0;
1150 }
1151
1152 reply_msg = gprs_gsup_msgb_alloc();
1153 reply_msg->l2h = reply_msg->data;
1154 gprs_gsup_encode(reply_msg, &from_peer);
1155 gprs_subscr_rx_gsup_message(reply_msg);
1156 msgb_free(reply_msg);
1157
1158 return 0;
1159};
1160
1161static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1162{
1163 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1164 struct gsm_subscriber *subscr;
1165
1166 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1167 sgsn_inst.cfg.subscriber_expiry_timeout = 0;
1168 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1169
1170 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1171
1172 if (retry) {
1173 upd_loc_skip = 3;
1174 auth_info_skip = 3;
1175 }
1176
1177 printf("Auth policy 'remote', real GSUP based auth: ");
1178 test_gmm_attach(retry);
1179
1180 subscr = gprs_subscr_get_by_imsi("123456789012345");
1181 OSMO_ASSERT(subscr != NULL);
1182 gprs_subscr_delete(subscr);
1183
1184 osmo_timers_update();
1185
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +01001186 assert_no_subscrs();
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001187
1188 sgsn->cfg.auth_policy = saved_auth_policy;
1189 sgsn_inst.cfg.subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER;
1190 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1191 upd_loc_skip = 0;
1192 auth_info_skip = 0;
1193 talloc_free(sgsn->gsup_client);
1194 sgsn->gsup_client = NULL;
1195}
1196
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001197/*
1198 * Test the GMM Rejects
1199 */
1200static void test_gmm_reject(void)
1201{
1202 struct gprs_ra_id raid = { 0, };
1203 struct sgsn_mm_ctx *ctx = NULL;
1204 uint32_t foreign_tlli;
1205 struct gprs_llc_lle *lle;
1206 int idx;
1207
1208 /* DTAP - Attach Request */
1209 /* Invalid MI length */
1210 static const unsigned char attach_req_inv_mi_len[] = {
1211 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1212 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1213 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1214 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1215 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1216 };
1217
1218 /* DTAP - Attach Request */
1219 /* Invalid MI type (IMEI) */
1220 static const unsigned char attach_req_inv_mi_type[] = {
1221 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1222 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1223 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1224 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1225 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1226 };
1227
1228 /* DTAP - Routing Area Update Request */
1229 static const unsigned char dtap_ra_upd_req[] = {
1230 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1231 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1232 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1233 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1234 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1235 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1236 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1237 };
1238
1239 /* DTAP - Routing Area Update Request */
1240 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1241 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1242 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1243 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1244 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1245 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1246 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1247 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1248 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1249 };
1250
1251 /* DTAP - Routing Area Update Request */
1252 /* Invalid cap length */
1253 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1254 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1255 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1256 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1257 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1258 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1259 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1260 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1261 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1262 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1263 };
1264
1265 struct test {
1266 const char *title;
1267 const unsigned char *msg;
1268 unsigned msg_len;
1269 unsigned num_resp;
1270
1271 };
1272 static struct test tests[] = {
1273 {
1274 .title = "Attach Request (invalid MI length)",
1275 .msg = attach_req_inv_mi_len,
1276 .msg_len = sizeof(attach_req_inv_mi_len),
1277 .num_resp = 1 /* Reject */
1278
1279 },
1280 {
1281 .title = "Attach Request (invalid MI type)",
1282 .msg = attach_req_inv_mi_type,
1283 .msg_len = sizeof(attach_req_inv_mi_type),
1284 .num_resp = 1 /* Reject */
1285 },
1286 {
1287 .title = "Routing Area Update Request (valid)",
1288 .msg = dtap_ra_upd_req,
1289 .msg_len = sizeof(dtap_ra_upd_req),
1290 .num_resp = 2 /* XID Reset + Reject */
1291 },
1292 {
1293 .title = "Routing Area Update Request (invalid type)",
1294 .msg = dtap_ra_upd_req_inv_type,
1295 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1296 .num_resp = 1 /* Reject */
1297 },
1298 {
1299 .title = "Routing Area Update Request (invalid CAP length)",
1300 .msg = dtap_ra_upd_req_inv_cap_len,
1301 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1302 .num_resp = 1 /* Reject */
1303 },
1304 };
1305
1306 printf("Testing GMM reject\n");
1307
1308 /* reset the PRNG used by sgsn_alloc_ptmsi */
1309 srand(1);
1310
1311 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1312
1313 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1314
1315 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1316 const struct test *test = &tests[idx];
1317 printf(" - %s\n", test->title);
1318
1319 /* Create a LLE/LLME */
1320 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1321 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1322
1323 /* Inject the Request message */
1324 send_0408_message(lle->llme, foreign_tlli,
1325 test->msg, test->msg_len);
1326
1327 /* We expect a Reject message */
1328 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1329 sgsn_tx_counter, test->num_resp);
1330 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1331
1332 /* verify that LLME/MM are removed */
1333 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1334 OSMO_ASSERT(ctx == NULL);
1335 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1336 }
1337}
1338
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001339/*
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001340 * Test cancellation of attached MM contexts
1341 */
1342static void test_gmm_cancel(void)
1343{
1344 struct gprs_ra_id raid = { 0, };
1345 struct sgsn_mm_ctx *ctx = NULL;
1346 struct sgsn_mm_ctx *ictx;
1347 uint32_t ptmsi1;
1348 uint32_t foreign_tlli;
1349 uint32_t local_tlli = 0;
1350 struct gprs_llc_lle *lle;
1351 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1352
1353 /* DTAP - Attach Request */
1354 /* The P-TMSI is not known by the SGSN */
1355 static const unsigned char attach_req[] = {
1356 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1357 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1358 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1359 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1360 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1361 };
1362
1363 /* DTAP - Identity Response IMEI */
1364 static const unsigned char ident_resp_imei[] = {
1365 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1366 0x56
1367 };
1368
1369 /* DTAP - Identity Response IMSI */
1370 static const unsigned char ident_resp_imsi[] = {
1371 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1372 0x54
1373 };
1374
1375 /* DTAP - Attach Complete */
1376 static const unsigned char attach_compl[] = {
1377 0x08, 0x03
1378 };
1379
1380 printf("Testing cancellation\n");
1381
1382 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1383
1384 /* reset the PRNG used by sgsn_alloc_ptmsi */
1385 srand(1);
1386
1387 ptmsi1 = sgsn_alloc_ptmsi();
1388 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1389
1390 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1391 * again */
1392 srand(1);
1393
1394 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1395
1396 /* Create a LLE/LLME */
1397 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1398 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1399 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1400
1401 /* inject the attach request */
1402 send_0408_message(lle->llme, foreign_tlli,
1403 attach_req, ARRAY_SIZE(attach_req));
1404
1405 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1406 OSMO_ASSERT(ctx != NULL);
1407 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1408
1409 /* we expect an identity request (IMEI) */
1410 OSMO_ASSERT(sgsn_tx_counter == 1);
1411
1412 /* inject the identity response (IMEI) */
1413 send_0408_message(ctx->llme, foreign_tlli,
1414 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1415
1416 /* we expect an identity request (IMSI) */
1417 OSMO_ASSERT(sgsn_tx_counter == 1);
1418
1419 /* inject the identity response (IMSI) */
1420 send_0408_message(ctx->llme, foreign_tlli,
1421 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1422
1423 /* check that the MM context has not been removed due to a failed
1424 * authorization */
1425 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1426
1427 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1428
1429 /* we expect an attach accept/reject */
1430 OSMO_ASSERT(sgsn_tx_counter == 1);
1431
1432 /* this has been randomly assigned by the SGSN */
1433 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1434
1435 /* inject the attach complete */
1436 send_0408_message(ctx->llme, local_tlli,
1437 attach_compl, ARRAY_SIZE(attach_compl));
1438
1439 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1440
1441 /* we don't expect a response */
1442 OSMO_ASSERT(sgsn_tx_counter == 0);
1443
1444 /* cancel */
Jacob Erlbeck41010082015-01-05 17:51:17 +01001445 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001446
1447 /* verify that things are gone */
1448 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1449 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1450 OSMO_ASSERT(!ictx);
1451
1452 sgsn->cfg.auth_policy = saved_auth_policy;
1453}
1454
1455/*
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001456 * Test the dynamic allocation of P-TMSIs
1457 */
1458static void test_gmm_ptmsi_allocation(void)
1459{
1460 struct gprs_ra_id raid = { 0, };
1461 struct sgsn_mm_ctx *ctx = NULL;
1462 struct sgsn_mm_ctx *ictx;
1463 uint32_t foreign_tlli;
1464 uint32_t ptmsi1;
1465 uint32_t ptmsi2;
1466 uint32_t old_ptmsi;
1467 uint32_t local_tlli = 0;
1468 struct gprs_llc_lle *lle;
1469 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1470
1471 /* DTAP - Attach Request (IMSI 12131415161718) */
1472 static const unsigned char attach_req[] = {
1473 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1474 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1475 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1476 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1477 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1478 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1479 0x00,
1480 };
1481
1482 /* DTAP - Identity Response IMEI */
1483 static const unsigned char ident_resp_imei[] = {
1484 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1485 0x56
1486 };
1487
1488 /* DTAP - Attach Complete */
1489 static const unsigned char attach_compl[] = {
1490 0x08, 0x03
1491 };
1492
1493 /* DTAP - Routing Area Update Request */
1494 static const unsigned char ra_upd_req[] = {
1495 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1496 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1497 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1498 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1499 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1500 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1501 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1502 };
1503
1504 /* DTAP - Routing Area Update Complete */
1505 static const unsigned char ra_upd_complete[] = {
1506 0x08, 0x0a
1507 };
1508
1509 /* DTAP - Detach Request (MO) */
1510 /* normal detach, power_off = 1 */
1511 static const unsigned char detach_req[] = {
1512 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1513 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1514 };
1515
1516 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1517
1518 printf("Testing P-TMSI allocation\n");
1519
1520 printf(" - sgsn_alloc_ptmsi\n");
1521
1522 /* reset the PRNG used by sgsn_alloc_ptmsi */
1523 srand(1);
1524
1525 ptmsi1 = sgsn_alloc_ptmsi();
1526 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1527
1528 ptmsi2 = sgsn_alloc_ptmsi();
1529 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1530
1531 OSMO_ASSERT(ptmsi1 != ptmsi2);
1532
1533 printf(" - Repeated Attach Request\n");
1534
1535 /* reset the PRNG, so that the same P-TMSI will be generated
1536 * again */
1537 srand(1);
1538
1539 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1540
1541 /* Create a LLE/LLME */
1542 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1543 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1544 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1545
1546 /* inject the attach request */
1547 send_0408_message(lle->llme, foreign_tlli,
1548 attach_req, ARRAY_SIZE(attach_req));
1549
1550 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1551 OSMO_ASSERT(ctx != NULL);
1552 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1553 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1554
1555 old_ptmsi = ctx->p_tmsi_old;
1556
1557 /* we expect an identity request (IMEI) */
1558 OSMO_ASSERT(sgsn_tx_counter == 1);
1559
1560 /* inject the identity response (IMEI) */
1561 send_0408_message(ctx->llme, foreign_tlli,
1562 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1563
1564 /* check that the MM context has not been removed due to a failed
1565 * authorization */
1566 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1567
1568 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1569 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1570
1571 /* we expect an attach accept */
1572 OSMO_ASSERT(sgsn_tx_counter == 1);
1573
1574 /* we ignore this and send the attach again */
1575 send_0408_message(lle->llme, foreign_tlli,
1576 attach_req, ARRAY_SIZE(attach_req));
1577
1578 /* the allocated P-TMSI should be the same */
1579 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1580 OSMO_ASSERT(ctx != NULL);
1581 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1582 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1583 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1584
1585 /* inject the attach complete */
1586 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1587 send_0408_message(ctx->llme, local_tlli,
1588 attach_compl, ARRAY_SIZE(attach_compl));
1589
1590 /* we don't expect a response */
1591 OSMO_ASSERT(sgsn_tx_counter == 0);
1592
1593 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1594 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1595 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1596
1597 printf(" - Repeated RA Update Request\n");
1598
1599 /* inject the RA update request */
1600 send_0408_message(ctx->llme, local_tlli,
1601 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1602
1603 /* we expect an RA update accept */
1604 OSMO_ASSERT(sgsn_tx_counter == 1);
1605
1606 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1607 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1608 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1609
1610 /* repeat the RA update request */
1611 send_0408_message(ctx->llme, local_tlli,
1612 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1613
1614 /* we expect an RA update accept */
1615 OSMO_ASSERT(sgsn_tx_counter == 1);
1616
1617 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1618 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1619 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1620
1621 /* inject the RA update complete */
1622 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1623 send_0408_message(ctx->llme, local_tlli,
1624 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1625
1626 /* we don't expect a response */
1627 OSMO_ASSERT(sgsn_tx_counter == 0);
1628
1629 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1630 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1631 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1632
1633 /* inject the detach */
1634 send_0408_message(ctx->llme, local_tlli,
1635 detach_req, ARRAY_SIZE(detach_req));
1636
1637 /* verify that things are gone */
1638 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1639 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1640 OSMO_ASSERT(!ictx);
1641
1642 sgsn->cfg.auth_policy = saved_auth_policy;
1643}
1644
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001645static struct log_info_cat gprs_categories[] = {
1646 [DMM] = {
1647 .name = "DMM",
1648 .description = "Layer3 Mobility Management (MM)",
1649 .color = "\033[1;33m",
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001650 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001651 },
1652 [DPAG] = {
1653 .name = "DPAG",
1654 .description = "Paging Subsystem",
1655 .color = "\033[1;38m",
1656 .enabled = 1, .loglevel = LOGL_NOTICE,
1657 },
1658 [DMEAS] = {
1659 .name = "DMEAS",
1660 .description = "Radio Measurement Processing",
1661 .enabled = 0, .loglevel = LOGL_NOTICE,
1662 },
1663 [DREF] = {
1664 .name = "DREF",
1665 .description = "Reference Counting",
1666 .enabled = 0, .loglevel = LOGL_NOTICE,
1667 },
1668 [DGPRS] = {
1669 .name = "DGPRS",
1670 .description = "GPRS Packet Service",
1671 .enabled = 1, .loglevel = LOGL_DEBUG,
1672 },
1673 [DNS] = {
1674 .name = "DNS",
1675 .description = "GPRS Network Service (NS)",
1676 .enabled = 1, .loglevel = LOGL_INFO,
1677 },
1678 [DBSSGP] = {
1679 .name = "DBSSGP",
1680 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1681 .enabled = 1, .loglevel = LOGL_DEBUG,
1682 },
1683 [DLLC] = {
1684 .name = "DLLC",
1685 .description = "GPRS Logical Link Control Protocol (LLC)",
1686 .enabled = 1, .loglevel = LOGL_DEBUG,
1687 },
1688 [DSNDCP] = {
1689 .name = "DSNDCP",
1690 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1691 .enabled = 1, .loglevel = LOGL_DEBUG,
1692 },
1693};
1694
1695static struct log_info info = {
1696 .cat = gprs_categories,
1697 .num_cat = ARRAY_SIZE(gprs_categories),
1698};
1699
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001700int main(int argc, char **argv)
1701{
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001702 osmo_init_logging(&info);
1703 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1704 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1705
Jacob Erlbeckb2acd742014-11-13 10:48:39 +01001706 sgsn_auth_init();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001707 gprs_subscr_init(sgsn);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001708
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001709 test_llme();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001710 test_subscriber();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +01001711 test_auth_triplets();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +01001712 test_subscriber_gsup();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +02001713 test_gmm_detach();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +01001714 test_gmm_detach_power_off();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001715 test_gmm_detach_no_mmctx();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +01001716 test_gmm_detach_accept_unexpected();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001717 test_gmm_status_no_mmctx();
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +01001718 test_gmm_attach_acl();
1719 test_gmm_attach_subscr();
Jacob Erlbeckd8126992014-12-08 15:26:47 +01001720 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck828059f2014-11-28 14:55:25 +01001721 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001722 test_gmm_attach_subscr_gsup_auth(0);
1723 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001724 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001725 test_gmm_reject();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001726 test_gmm_cancel();
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001727 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001728 printf("Done\n");
Jacob Erlbeck80dbcf12015-01-13 11:46:32 +01001729
1730 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeck6e6b3302015-01-13 11:56:28 +01001731 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001732 return 0;
1733}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001734
1735
1736/* stubs */
1737struct osmo_prim_hdr;
1738int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1739{
1740 abort();
1741}