blob: da1cb4b128416b5c373c5bc146b4ea01bc3483e2 [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 Erlbeck33b6dad2014-11-12 10:12:11 +0100214static void test_subscriber(void)
215{
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100216 struct gsm_subscriber *s1, *s2, *s3, *sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100217 const char *imsi1 = "1234567890";
218 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100219 const char *imsi3 = "5656565656";
220 int saved_expiry_timeout = sgsn->cfg.subscriber_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100221
222 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
223
224 printf("Testing core subscriber data API\n");
225
226 /* Check for emptiness */
227 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
228 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100229 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100230
231 /* Allocate entry 1 */
232 s1 = gprs_subscr_get_or_create(imsi1);
233 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100234 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100235 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100236
237 /* Allocate entry 2 */
238 s2 = gprs_subscr_get_or_create(imsi2);
239 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100240
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100241 /* Allocate entry 3 */
242 s3 = gprs_subscr_get_or_create(imsi3);
243
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100244 /* Check entries */
245 assert_subscr(s1, imsi1);
246 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100247 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100248
249 /* Update entry 1 */
250 last_updated_subscr = NULL;
251 gprs_subscr_update(s1);
252 OSMO_ASSERT(last_updated_subscr == s1);
253
254 /* Because of the update, it won't be freed on delete now */
255 gprs_subscr_delete(s1);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100256 sfound = gprs_subscr_get_by_imsi(imsi1);
257 OSMO_ASSERT(sfound != NULL);
258 s1 = sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100259
260 /* Cancel it, so that delete will free it.
261 * Refcount it to make sure s1 won't be freed here */
262 last_updated_subscr = NULL;
263 gprs_subscr_put_and_cancel(subscr_get(s1));
264 OSMO_ASSERT(last_updated_subscr == s1);
265
266 /* Cancelled entries are still being found */
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100267 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100268
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100269 /* Free entry 1 (GPRS_SUBSCRIBER_CANCELLED is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100270 gprs_subscr_delete(s1);
271 s1 = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100272 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100273 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100274 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100275
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100276 /* Free entry 2 (GSM_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100277 gprs_subscr_delete(s2);
278 s2 = NULL;
279 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
280 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100281 assert_subscr(s3, imsi3);
282
283 /* Try to delete entry 3 */
284 OSMO_ASSERT(sgsn->cfg.subscriber_expiry_timeout == SGSN_TIMEOUT_NEVER);
285 gprs_subscr_delete(s3);
286 assert_subscr(s3, imsi3);
287 /* Process timeouts, this shouldn't delete s3 (SGSN_TIMEOUT_NEVER) */
288 osmo_timers_update();
289 assert_subscr(s3, imsi3);
290 s3 = subscr_get(s3);
291
292 /* Free entry 3 (TIMEOUT == 0) */
293 sgsn->cfg.subscriber_expiry_timeout = 0;
294 gprs_subscr_delete(s3);
295 assert_subscr(s3, imsi3);
296 /* Process timeouts, this should delete s3 */
297 osmo_timers_update();
298 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
299 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
300 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
301 sgsn->cfg.subscriber_expiry_timeout = saved_expiry_timeout;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100302
303 OSMO_ASSERT(llist_empty(&active_subscribers));
304
305 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
306}
307
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100308static void test_auth_triplets(void)
309{
310 struct gsm_subscriber *s1, *s1found;
311 const char *imsi1 = "1234567890";
312 struct gsm_auth_tuple *at;
313 struct sgsn_mm_ctx *ctx;
314 struct gprs_ra_id raid = { 0, };
315 uint32_t local_tlli = 0xffeeddcc;
316 struct gprs_llc_llme *llme;
317
318 printf("Testing authentication triplet handling\n");
319
320 /* Check for emptiness */
321 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
322
323 /* Allocate entry 1 */
324 s1 = gprs_subscr_get_or_create(imsi1);
325 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
326 s1found = gprs_subscr_get_by_imsi(imsi1);
327 OSMO_ASSERT(s1found == s1);
328 subscr_put(s1found);
329
330 /* Create a context */
331 OSMO_ASSERT(count(gprs_llme_list()) == 0);
332 ctx = alloc_mm_ctx(local_tlli, &raid);
333
334 /* Attach s1 to ctx */
335 ctx->subscr = subscr_get(s1);
336 ctx->subscr->sgsn_data->mm = ctx;
337
338 /* Try to get auth tuple */
339 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
340 OSMO_ASSERT(at == NULL);
341
342 /* Add triplets */
343 s1->sgsn_data->auth_triplets[0].key_seq = 0;
344 s1->sgsn_data->auth_triplets[1].key_seq = 1;
345 s1->sgsn_data->auth_triplets[2].key_seq = 2;
346
347 /* Try to get auth tuple */
348 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
349 OSMO_ASSERT(at != NULL);
350 OSMO_ASSERT(at->key_seq == 0);
351 OSMO_ASSERT(at->use_count == 1);
352 at = sgsn_auth_get_tuple(ctx, at->key_seq);
353 OSMO_ASSERT(at != NULL);
354 OSMO_ASSERT(at->key_seq == 1);
355 OSMO_ASSERT(at->use_count == 1);
356 at = sgsn_auth_get_tuple(ctx, at->key_seq);
357 OSMO_ASSERT(at != NULL);
358 OSMO_ASSERT(at->key_seq == 2);
359 OSMO_ASSERT(at->use_count == 1);
360 at = sgsn_auth_get_tuple(ctx, at->key_seq);
361 OSMO_ASSERT(at == NULL);
362
363 /* Free MM context and subscriber */
364 subscr_put(s1);
365 llme = ctx->llme;
366 sgsn_mm_ctx_free(ctx);
367 s1found = gprs_subscr_get_by_imsi(imsi1);
368 OSMO_ASSERT(s1found == NULL);
369 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
370}
371
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100372#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
373
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100374static int rx_gsup_message(const uint8_t *data, size_t data_len)
375{
376 struct msgb *msg;
377 int rc;
378
379 msg = msgb_alloc(1024, __func__);
380 msg->l2h = msgb_put(msg, data_len);
381 OSMO_ASSERT(msg->l2h != NULL);
382 memcpy(msg->l2h, data, data_len);
383 rc = gprs_subscr_rx_gsup_message(msg);
384 msgb_free(msg);
385
386 return rc;
387}
388
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100389static void test_subscriber_gsup(void)
390{
391 struct gsm_subscriber *s1, *s1found;
392 const char *imsi1 = "1234567890";
393 struct sgsn_mm_ctx *ctx;
394 struct gprs_ra_id raid = { 0, };
395 uint32_t local_tlli = 0xffeeddcc;
396 struct gprs_llc_llme *llme;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100397 int rc;
398
399 static const uint8_t send_auth_info_res[] = {
400 0x0a,
401 TEST_GSUP_IMSI1_IE,
402 0x03, 0x22, /* Auth tuple */
403 0x20, 0x10,
404 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
405 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
406 0x21, 0x04,
407 0x21, 0x22, 0x23, 0x24,
408 0x22, 0x08,
409 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
410 0x03, 0x22, /* Auth tuple */
411 0x20, 0x10,
412 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
413 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
414 0x21, 0x04,
415 0xa1, 0xa2, 0xa3, 0xa4,
416 0x22, 0x08,
417 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
418 };
419
420 static const uint8_t send_auth_info_err[] = {
421 0x09,
422 TEST_GSUP_IMSI1_IE,
423 0x02, 0x01, 0x07 /* GPRS not allowed */
424 };
425
426 static const uint8_t update_location_res[] = {
427 0x06,
428 TEST_GSUP_IMSI1_IE,
429 0x04, 0x00, /* PDP info complete */
430 0x05, 0x12,
431 0x10, 0x01, 0x01,
432 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
433 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
434 0x05, 0x11,
435 0x10, 0x01, 0x02,
436 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
437 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
438 };
439
440 static const uint8_t update_location_err[] = {
441 0x05,
442 TEST_GSUP_IMSI1_IE,
443 0x02, 0x01, 0x07 /* GPRS not allowed */
444 };
445
446 static const uint8_t location_cancellation_req[] = {
447 0x1c,
448 TEST_GSUP_IMSI1_IE,
449 0x06, 0x01, 0x00,
450 };
451
452 printf("Testing subcriber GSUP handling\n");
453
454 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
455
456 /* Check for emptiness */
457 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
458
459 /* Allocate entry 1 */
460 s1 = gprs_subscr_get_or_create(imsi1);
461 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
462 s1found = gprs_subscr_get_by_imsi(imsi1);
463 OSMO_ASSERT(s1found == s1);
464 subscr_put(s1found);
465
466 /* Create a context */
467 OSMO_ASSERT(count(gprs_llme_list()) == 0);
468 ctx = alloc_mm_ctx(local_tlli, &raid);
469 llme = ctx->llme;
470
471 /* Attach s1 to ctx */
472 ctx->subscr = subscr_get(s1);
473 ctx->subscr->sgsn_data->mm = ctx;
474
475 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100476 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100477 OSMO_ASSERT(rc >= 0);
478 OSMO_ASSERT(last_updated_subscr == s1);
479
480 /* Check triplets */
481 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
482 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
483 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
484
485 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100486 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100487 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100488 OSMO_ASSERT(last_updated_subscr == s1);
489
490 /* Check triplets */
491 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
492 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
493 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
494
495 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100496 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100497 OSMO_ASSERT(rc >= 0);
498 OSMO_ASSERT(last_updated_subscr == s1);
499
500 /* Check authorization */
501 OSMO_ASSERT(s1->authorized == 1);
502
503 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100504 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100505 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100506 OSMO_ASSERT(last_updated_subscr == s1);
507
508 /* Check authorization */
509 OSMO_ASSERT(s1->authorized == 0);
510
511 /* Inject UpdateLocReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100512 rc = rx_gsup_message(location_cancellation_req,
513 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100514 OSMO_ASSERT(rc >= 0);
515 OSMO_ASSERT(last_updated_subscr == s1);
516
517 /* Check cancellation result */
518 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
519 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
520
521 /* Free MM context and subscriber */
522 subscr_put(s1);
523 s1found = gprs_subscr_get_by_imsi(imsi1);
524 OSMO_ASSERT(s1found == NULL);
525 gprs_llgmm_assign(llme, local_tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
526
527 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
528}
529
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200530/*
531 * Test that a GMM Detach will remove the MMCTX and the
532 * associated LLME.
533 */
534static void test_gmm_detach(void)
535{
536 struct gprs_ra_id raid = { 0, };
537 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200538 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200539
540 printf("Testing GMM detach\n");
541
542 /* DTAP - Detach Request (MO) */
543 /* normal detach, power_off = 0 */
544 static const unsigned char detach_req[] = {
545 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
546 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
547 };
548
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200549 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200550
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100551 /* Create a context */
552 OSMO_ASSERT(count(gprs_llme_list()) == 0);
553 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200554
555 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100556 send_0408_message(ctx->llme, local_tlli,
557 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200558
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100559 /* verify that a single message (hopefully the Detach Accept) has been
560 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100561 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100562
563 /* verify that things are gone */
564 OSMO_ASSERT(count(gprs_llme_list()) == 0);
565 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
566 OSMO_ASSERT(!ictx);
567}
568
569/*
570 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
571 * will not sent a Detach Accept message (power_off = 1)
572 */
573static void test_gmm_detach_power_off(void)
574{
575 struct gprs_ra_id raid = { 0, };
576 struct sgsn_mm_ctx *ctx, *ictx;
577 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100578
579 printf("Testing GMM detach (power off)\n");
580
581 /* DTAP - Detach Request (MO) */
582 /* normal detach, power_off = 1 */
583 static const unsigned char detach_req[] = {
584 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
585 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
586 };
587
588 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
589
590 /* Create a context */
591 OSMO_ASSERT(count(gprs_llme_list()) == 0);
592 ctx = alloc_mm_ctx(local_tlli, &raid);
593
594 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100595 send_0408_message(ctx->llme, local_tlli,
596 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100597
598 /* verify that no message (and therefore no Detach Accept) has been
599 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100600 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100601
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200602 /* verify that things are gone */
603 OSMO_ASSERT(count(gprs_llme_list()) == 0);
604 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200605 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200606}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200607
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200608/*
609 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
610 */
611static void test_gmm_detach_no_mmctx(void)
612{
613 struct gprs_llc_lle *lle;
614 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200615
616 printf("Testing GMM detach (no MMCTX)\n");
617
618 /* DTAP - Detach Request (MO) */
619 /* normal detach, power_off = 0 */
620 static const unsigned char detach_req[] = {
621 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
622 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
623 };
624
625 /* Create an LLME */
626 OSMO_ASSERT(count(gprs_llme_list()) == 0);
627 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
628 lle = gprs_lle_get_or_create(local_tlli, 3);
629
630 OSMO_ASSERT(count(gprs_llme_list()) == 1);
631
632 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100633 send_0408_message(lle->llme, local_tlli,
634 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200635
636 /* verify that the LLME is gone */
637 OSMO_ASSERT(count(gprs_llme_list()) == 0);
638}
639
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100640/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100641 * Test that a single GMM Detach Accept message will not cause the SGSN to send
642 * any message or leave an MM context at the SGSN.
643 */
644static void test_gmm_detach_accept_unexpected(void)
645{
646 struct gprs_llc_lle *lle;
647 uint32_t local_tlli;
648
649 printf("Testing GMM detach accept (unexpected)\n");
650
651 /* DTAP - Detach Accept (MT) */
652 /* normal detach */
653 static const unsigned char detach_acc[] = {
654 0x08, 0x06
655 };
656
657 /* Create an LLME */
658 OSMO_ASSERT(count(gprs_llme_list()) == 0);
659 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
660 lle = gprs_lle_get_or_create(local_tlli, 3);
661
662 /* inject the detach */
663 send_0408_message(lle->llme, local_tlli,
664 detach_acc, ARRAY_SIZE(detach_acc));
665
666 /* verify that no message (and therefore no Status or XID reset) has been
667 * sent by the SGSN */
668 OSMO_ASSERT(sgsn_tx_counter == 0);
669
670 /* verify that things are gone */
671 OSMO_ASSERT(count(gprs_llme_list()) == 0);
672}
673
674/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100675 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
676 */
677static void test_gmm_status_no_mmctx(void)
678{
679 struct gprs_llc_lle *lle;
680 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100681
682 printf("Testing GMM Status (no MMCTX)\n");
683
684 /* DTAP - GMM Status, protocol error */
685 static const unsigned char gmm_status[] = {
686 0x08, 0x20, 0x6f
687 };
688
689 /* Create an LLME */
690 OSMO_ASSERT(count(gprs_llme_list()) == 0);
691 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
692 lle = gprs_lle_get_or_create(local_tlli, 3);
693
694 OSMO_ASSERT(count(gprs_llme_list()) == 1);
695
696 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100697 send_0408_message(lle->llme, local_tlli,
698 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100699
700 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100701 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100702
703 /* verify that the LLME is gone */
704 OSMO_ASSERT(count(gprs_llme_list()) == 0);
705}
706
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100707/*
708 * Test the GMM Attach procedure
709 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100710static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100711{
712 struct gprs_ra_id raid = { 0, };
713 struct sgsn_mm_ctx *ctx = NULL;
714 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100715 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100716 uint32_t foreign_tlli;
717 uint32_t local_tlli = 0;
718 struct gprs_llc_lle *lle;
719
720 /* DTAP - Attach Request */
721 /* The P-TMSI is not known by the SGSN */
722 static const unsigned char attach_req[] = {
723 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
724 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
725 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
726 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
727 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
728 };
729
730 /* DTAP - Identity Response IMEI */
731 static const unsigned char ident_resp_imei[] = {
732 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
733 0x56
734 };
735
736 /* DTAP - Identity Response IMSI */
737 static const unsigned char ident_resp_imsi[] = {
738 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
739 0x54
740 };
741
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100742 /* DTAP - Authentication and Ciphering Resp */
743 static const unsigned char auth_ciph_resp[] = {
744 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
745 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
746 };
747
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100748 /* DTAP - Attach Complete */
749 static const unsigned char attach_compl[] = {
750 0x08, 0x03
751 };
752
753 /* DTAP - Detach Request (MO) */
754 /* normal detach, power_off = 0 */
755 static const unsigned char detach_req[] = {
756 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
757 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
758 };
759
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100760 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100761
762 /* reset the PRNG used by sgsn_alloc_ptmsi */
763 srand(1);
764
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100765 ptmsi1 = sgsn_alloc_ptmsi();
766 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
767
768 /* reset the PRNG, so that the same P-TMSI sequence will be generated
769 * again */
770 srand(1);
771
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100772 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
773
774 /* Create a LLE/LLME */
775 OSMO_ASSERT(count(gprs_llme_list()) == 0);
776 lle = gprs_lle_get_or_create(foreign_tlli, 3);
777 OSMO_ASSERT(count(gprs_llme_list()) == 1);
778
779 /* inject the attach request */
780 send_0408_message(lle->llme, foreign_tlli,
781 attach_req, ARRAY_SIZE(attach_req));
782
783 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
784 OSMO_ASSERT(ctx != NULL);
785 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
786
787 /* we expect an identity request (IMEI) */
788 OSMO_ASSERT(sgsn_tx_counter == 1);
789
790 /* inject the identity response (IMEI) */
791 send_0408_message(ctx->llme, foreign_tlli,
792 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
793
794 /* we expect an identity request (IMSI) */
795 OSMO_ASSERT(sgsn_tx_counter == 1);
796
797 /* inject the identity response (IMSI) */
798 send_0408_message(ctx->llme, foreign_tlli,
799 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
800
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100801 /* check that the MM context has not been removed due to a failed
802 * authorization */
803 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
804
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100805 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100806
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100807retry_attach_req:
808
809 if (retry && sgsn_tx_counter == 0) {
810 fprintf(stderr, "Retrying attach request\n");
811 /* re-inject the attach request */
812 send_0408_message(lle->llme, foreign_tlli,
813 attach_req, ARRAY_SIZE(attach_req));
814 }
815
816 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
817 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100818
819 /* inject the auth & ciph response */
820 send_0408_message(ctx->llme, foreign_tlli,
821 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
822
823 /* check that the MM context has not been removed due to a
824 * failed authorization */
825 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
826 }
827
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100828 if (retry && sgsn_tx_counter == 0)
829 goto retry_attach_req;
830
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100831 /* we expect an attach accept/reject */
832 OSMO_ASSERT(sgsn_tx_counter == 1);
833
834 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100835 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100836
837 /* inject the attach complete */
838 send_0408_message(ctx->llme, local_tlli,
839 attach_compl, ARRAY_SIZE(attach_compl));
840
841 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
842
843 /* we don't expect a response */
844 OSMO_ASSERT(sgsn_tx_counter == 0);
845
846 /* inject the detach */
847 send_0408_message(ctx->llme, local_tlli,
848 detach_req, ARRAY_SIZE(detach_req));
849
850 /* verify that things are gone */
851 OSMO_ASSERT(count(gprs_llme_list()) == 0);
852 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
853 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100854}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100855
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100856static void test_gmm_attach_acl(void)
857{
858 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
859
860 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
861 sgsn_acl_add("123456789012345", &sgsn->cfg);
862 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100863 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100864 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100865
866 sgsn->cfg.auth_policy = saved_auth_policy;
867}
868
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100869int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100870 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100871 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100872 if (rc == -ENOTSUP) {
873 OSMO_ASSERT(mmctx->subscr);
874 gprs_subscr_update(mmctx->subscr);
875 }
876 return rc;
877};
878
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100879int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
880 gprs_subscr_update(mmctx->subscr);
881 return 0;
882};
883
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100884static void cleanup_subscr_by_imsi(const char *imsi)
885{
886 struct gsm_subscriber *subscr;
887
888 subscr = gprs_subscr_get_by_imsi(imsi);
889 OSMO_ASSERT(subscr != NULL);
Jacob Erlbecke1beb6f2015-01-08 14:13:46 +0100890 subscr->keep_in_ram = 0;
891 subscr_put(subscr);
892 subscr = gprs_subscr_get_by_imsi(imsi);
893 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100894}
895
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100896static void test_gmm_attach_subscr(void)
897{
898 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
899 struct gsm_subscriber *subscr;
900
901 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100902 subscr_request_update_location_cb = my_subscr_request_update_location;
903 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100904
905 subscr = gprs_subscr_get_or_create("123456789012345");
906 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100907 subscr->keep_in_ram = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100908 subscr_put(subscr);
909
910 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100911 test_gmm_attach(0);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100912
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100913 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100914
915 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100916 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
917 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100918}
919
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100920int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
921{
922 /* Fake an authentication */
923 OSMO_ASSERT(mmctx->subscr);
924 mmctx->is_authenticated = 1;
925 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100926
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100927 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100928};
929
930static void test_gmm_attach_subscr_fake_auth(void)
931{
932 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
933 struct gsm_subscriber *subscr;
934
935 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100936 subscr_request_update_location_cb = my_subscr_request_update_location;
937 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100938
939 subscr = gprs_subscr_get_or_create("123456789012345");
940 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100941 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100942 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100943 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100944 subscr_put(subscr);
945
946 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100947 test_gmm_attach(0);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100948
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100949 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100950
951 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100952 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
953 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
954}
955
956int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
957{
958 struct gsm_auth_tuple at = {
959 .sres = {0x51, 0xe5, 0x51, 0xe5},
960 .key_seq = 0
961 };
962
963 /* Fake an authentication */
964 OSMO_ASSERT(mmctx->subscr);
965 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
966
967 gprs_subscr_update_auth_info(mmctx->subscr);
968
969 return 0;
970};
971
972static void test_gmm_attach_subscr_real_auth(void)
973{
974 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
975 struct gsm_subscriber *subscr;
976
977 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
978 subscr_request_update_location_cb = my_subscr_request_update_location;
979 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
980
981 subscr = gprs_subscr_get_or_create("123456789012345");
982 subscr->authorized = 1;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100983 subscr->keep_in_ram = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +0100984 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +0100985 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100986 subscr_put(subscr);
987
988 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100989 test_gmm_attach(0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100990
Jacob Erlbeckd3cde1e2015-01-08 14:08:16 +0100991 cleanup_subscr_by_imsi("123456789012345");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100992
993 sgsn->cfg.auth_policy = saved_auth_policy;
994 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
995 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100996}
997
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100998#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
999 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
1000
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001001static int auth_info_skip = 0;
1002static int upd_loc_skip = 0;
1003
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001004int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
1005{
1006 static const uint8_t send_auth_info_res[] = {
1007 0x0a,
1008 TEST_GSUP_IMSI_LONG_IE,
1009 0x03, 0x22, /* Auth tuple */
1010 0x20, 0x10,
1011 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1012 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1013 0x21, 0x04,
1014 0x51, 0xe5, 0x51, 0xe5,
1015 0x22, 0x08,
1016 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1017 };
1018
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001019 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001020
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001021 if (auth_info_skip > 0) {
1022 auth_info_skip -= 1;
1023 return -EAGAIN;
1024 }
1025
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001026 /* Fake an SendAuthInfoRes */
1027 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1028
1029 return 0;
1030};
1031
1032int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1033 static const uint8_t update_location_res[] = {
1034 0x06,
1035 TEST_GSUP_IMSI_LONG_IE,
1036 0x04, 0x00, /* PDP info complete */
1037 0x05, 0x12,
1038 0x10, 0x01, 0x01,
1039 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1040 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
1041 };
1042
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001043 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001044
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001045 if (upd_loc_skip > 0) {
1046 upd_loc_skip -= 1;
1047 return -EAGAIN;
1048 }
1049
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001050 /* Fake an UpdateLocRes */
1051 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1052};
1053
1054
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001055static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001056{
1057 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1058 struct gsm_subscriber *subscr;
1059
1060 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1061 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1062 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001063 if (retry) {
1064 upd_loc_skip = 3;
1065 auth_info_skip = 3;
1066 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001067
1068 subscr = gprs_subscr_get_or_create("123456789012345");
1069 subscr->authorized = 1;
1070 sgsn->cfg.require_authentication = 1;
1071 sgsn->cfg.require_update_location = 1;
1072 subscr_put(subscr);
1073
1074 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001075 test_gmm_attach(retry);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001076
1077 subscr = gprs_subscr_get_by_imsi("123456789012345");
1078 OSMO_ASSERT(subscr != NULL);
1079 gprs_subscr_delete(subscr);
1080
1081 sgsn->cfg.auth_policy = saved_auth_policy;
1082 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1083 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001084 upd_loc_skip = 0;
1085 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001086}
1087
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001088int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1089{
1090 struct gprs_gsup_message to_peer;
1091 struct gprs_gsup_message from_peer;
1092 struct msgb *reply_msg;
1093
1094 /* Simulate the GSUP peer */
1095 gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1096
1097 /* This invalidates the pointers in to_peer */
1098 msgb_free(msg);
1099
1100 switch (to_peer.message_type) {
1101 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1102 /* Send UPDATE_LOCATION_RESULT */
1103 return my_subscr_request_update_gsup_auth(NULL);
1104
1105 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1106 /* Send SEND_AUTH_INFO_RESULT */
1107 return my_subscr_request_auth_info_gsup_auth(NULL);
1108
1109 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
1110 /* TODO: send RES/ERR */
1111 return 0;
1112
1113 default:
1114 if ((to_peer.message_type & 0b00000011) == 0) {
1115 /* Unhandled request */
1116 /* TODO: send error(NOT_IMPL) */
1117 from_peer.message_type = to_peer.message_type + 1;
1118 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1119 break;
1120 }
1121
1122 /* Ignore it */
1123 return 0;
1124 }
1125
1126 reply_msg = gprs_gsup_msgb_alloc();
1127 reply_msg->l2h = reply_msg->data;
1128 gprs_gsup_encode(reply_msg, &from_peer);
1129 gprs_subscr_rx_gsup_message(reply_msg);
1130 msgb_free(reply_msg);
1131
1132 return 0;
1133};
1134
1135static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1136{
1137 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1138 struct gsm_subscriber *subscr;
1139
1140 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1141 sgsn_inst.cfg.subscriber_expiry_timeout = 0;
1142 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1143
1144 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1145
1146 if (retry) {
1147 upd_loc_skip = 3;
1148 auth_info_skip = 3;
1149 }
1150
1151 printf("Auth policy 'remote', real GSUP based auth: ");
1152 test_gmm_attach(retry);
1153
1154 subscr = gprs_subscr_get_by_imsi("123456789012345");
1155 OSMO_ASSERT(subscr != NULL);
1156 gprs_subscr_delete(subscr);
1157
1158 osmo_timers_update();
1159
1160 OSMO_ASSERT(gprs_subscr_get_by_imsi("123456789012345") == NULL);
1161
1162 sgsn->cfg.auth_policy = saved_auth_policy;
1163 sgsn_inst.cfg.subscriber_expiry_timeout = SGSN_TIMEOUT_NEVER;
1164 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1165 upd_loc_skip = 0;
1166 auth_info_skip = 0;
1167 talloc_free(sgsn->gsup_client);
1168 sgsn->gsup_client = NULL;
1169}
1170
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001171/*
1172 * Test the GMM Rejects
1173 */
1174static void test_gmm_reject(void)
1175{
1176 struct gprs_ra_id raid = { 0, };
1177 struct sgsn_mm_ctx *ctx = NULL;
1178 uint32_t foreign_tlli;
1179 struct gprs_llc_lle *lle;
1180 int idx;
1181
1182 /* DTAP - Attach Request */
1183 /* Invalid MI length */
1184 static const unsigned char attach_req_inv_mi_len[] = {
1185 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1186 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1187 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1188 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1189 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1190 };
1191
1192 /* DTAP - Attach Request */
1193 /* Invalid MI type (IMEI) */
1194 static const unsigned char attach_req_inv_mi_type[] = {
1195 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1196 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1197 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1198 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1199 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1200 };
1201
1202 /* DTAP - Routing Area Update Request */
1203 static const unsigned char dtap_ra_upd_req[] = {
1204 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1205 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1206 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1207 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1208 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1209 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1210 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1211 };
1212
1213 /* DTAP - Routing Area Update Request */
1214 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1215 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1216 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1217 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1218 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1219 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1220 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1221 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1222 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1223 };
1224
1225 /* DTAP - Routing Area Update Request */
1226 /* Invalid cap length */
1227 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1228 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1229 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1230 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1231 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
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 struct test {
1240 const char *title;
1241 const unsigned char *msg;
1242 unsigned msg_len;
1243 unsigned num_resp;
1244
1245 };
1246 static struct test tests[] = {
1247 {
1248 .title = "Attach Request (invalid MI length)",
1249 .msg = attach_req_inv_mi_len,
1250 .msg_len = sizeof(attach_req_inv_mi_len),
1251 .num_resp = 1 /* Reject */
1252
1253 },
1254 {
1255 .title = "Attach Request (invalid MI type)",
1256 .msg = attach_req_inv_mi_type,
1257 .msg_len = sizeof(attach_req_inv_mi_type),
1258 .num_resp = 1 /* Reject */
1259 },
1260 {
1261 .title = "Routing Area Update Request (valid)",
1262 .msg = dtap_ra_upd_req,
1263 .msg_len = sizeof(dtap_ra_upd_req),
1264 .num_resp = 2 /* XID Reset + Reject */
1265 },
1266 {
1267 .title = "Routing Area Update Request (invalid type)",
1268 .msg = dtap_ra_upd_req_inv_type,
1269 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1270 .num_resp = 1 /* Reject */
1271 },
1272 {
1273 .title = "Routing Area Update Request (invalid CAP length)",
1274 .msg = dtap_ra_upd_req_inv_cap_len,
1275 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1276 .num_resp = 1 /* Reject */
1277 },
1278 };
1279
1280 printf("Testing GMM reject\n");
1281
1282 /* reset the PRNG used by sgsn_alloc_ptmsi */
1283 srand(1);
1284
1285 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1286
1287 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1288
1289 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1290 const struct test *test = &tests[idx];
1291 printf(" - %s\n", test->title);
1292
1293 /* Create a LLE/LLME */
1294 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1295 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1296
1297 /* Inject the Request message */
1298 send_0408_message(lle->llme, foreign_tlli,
1299 test->msg, test->msg_len);
1300
1301 /* We expect a Reject message */
1302 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1303 sgsn_tx_counter, test->num_resp);
1304 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1305
1306 /* verify that LLME/MM are removed */
1307 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1308 OSMO_ASSERT(ctx == NULL);
1309 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1310 }
1311}
1312
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001313/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001314 * Test cancellation of attached MM contexts
1315 */
1316static void test_gmm_cancel(void)
1317{
1318 struct gprs_ra_id raid = { 0, };
1319 struct sgsn_mm_ctx *ctx = NULL;
1320 struct sgsn_mm_ctx *ictx;
1321 uint32_t ptmsi1;
1322 uint32_t foreign_tlli;
1323 uint32_t local_tlli = 0;
1324 struct gprs_llc_lle *lle;
1325 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1326
1327 /* DTAP - Attach Request */
1328 /* The P-TMSI is not known by the SGSN */
1329 static const unsigned char attach_req[] = {
1330 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1331 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1332 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1333 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1334 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1335 };
1336
1337 /* DTAP - Identity Response IMEI */
1338 static const unsigned char ident_resp_imei[] = {
1339 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1340 0x56
1341 };
1342
1343 /* DTAP - Identity Response IMSI */
1344 static const unsigned char ident_resp_imsi[] = {
1345 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1346 0x54
1347 };
1348
1349 /* DTAP - Attach Complete */
1350 static const unsigned char attach_compl[] = {
1351 0x08, 0x03
1352 };
1353
1354 printf("Testing cancellation\n");
1355
1356 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1357
1358 /* reset the PRNG used by sgsn_alloc_ptmsi */
1359 srand(1);
1360
1361 ptmsi1 = sgsn_alloc_ptmsi();
1362 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1363
1364 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1365 * again */
1366 srand(1);
1367
1368 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1369
1370 /* Create a LLE/LLME */
1371 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1372 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1373 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1374
1375 /* inject the attach request */
1376 send_0408_message(lle->llme, foreign_tlli,
1377 attach_req, ARRAY_SIZE(attach_req));
1378
1379 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1380 OSMO_ASSERT(ctx != NULL);
1381 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1382
1383 /* we expect an identity request (IMEI) */
1384 OSMO_ASSERT(sgsn_tx_counter == 1);
1385
1386 /* inject the identity response (IMEI) */
1387 send_0408_message(ctx->llme, foreign_tlli,
1388 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1389
1390 /* we expect an identity request (IMSI) */
1391 OSMO_ASSERT(sgsn_tx_counter == 1);
1392
1393 /* inject the identity response (IMSI) */
1394 send_0408_message(ctx->llme, foreign_tlli,
1395 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1396
1397 /* check that the MM context has not been removed due to a failed
1398 * authorization */
1399 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1400
1401 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1402
1403 /* we expect an attach accept/reject */
1404 OSMO_ASSERT(sgsn_tx_counter == 1);
1405
1406 /* this has been randomly assigned by the SGSN */
1407 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1408
1409 /* inject the attach complete */
1410 send_0408_message(ctx->llme, local_tlli,
1411 attach_compl, ARRAY_SIZE(attach_compl));
1412
1413 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1414
1415 /* we don't expect a response */
1416 OSMO_ASSERT(sgsn_tx_counter == 0);
1417
1418 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001419 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001420
1421 /* verify that things are gone */
1422 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1423 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1424 OSMO_ASSERT(!ictx);
1425
1426 sgsn->cfg.auth_policy = saved_auth_policy;
1427}
1428
1429/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001430 * Test the dynamic allocation of P-TMSIs
1431 */
1432static void test_gmm_ptmsi_allocation(void)
1433{
1434 struct gprs_ra_id raid = { 0, };
1435 struct sgsn_mm_ctx *ctx = NULL;
1436 struct sgsn_mm_ctx *ictx;
1437 uint32_t foreign_tlli;
1438 uint32_t ptmsi1;
1439 uint32_t ptmsi2;
1440 uint32_t old_ptmsi;
1441 uint32_t local_tlli = 0;
1442 struct gprs_llc_lle *lle;
1443 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1444
1445 /* DTAP - Attach Request (IMSI 12131415161718) */
1446 static const unsigned char attach_req[] = {
1447 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1448 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1449 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1450 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1451 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1452 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1453 0x00,
1454 };
1455
1456 /* DTAP - Identity Response IMEI */
1457 static const unsigned char ident_resp_imei[] = {
1458 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1459 0x56
1460 };
1461
1462 /* DTAP - Attach Complete */
1463 static const unsigned char attach_compl[] = {
1464 0x08, 0x03
1465 };
1466
1467 /* DTAP - Routing Area Update Request */
1468 static const unsigned char ra_upd_req[] = {
1469 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1470 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1471 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1472 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1473 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1474 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1475 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1476 };
1477
1478 /* DTAP - Routing Area Update Complete */
1479 static const unsigned char ra_upd_complete[] = {
1480 0x08, 0x0a
1481 };
1482
1483 /* DTAP - Detach Request (MO) */
1484 /* normal detach, power_off = 1 */
1485 static const unsigned char detach_req[] = {
1486 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1487 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1488 };
1489
1490 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1491
1492 printf("Testing P-TMSI allocation\n");
1493
1494 printf(" - sgsn_alloc_ptmsi\n");
1495
1496 /* reset the PRNG used by sgsn_alloc_ptmsi */
1497 srand(1);
1498
1499 ptmsi1 = sgsn_alloc_ptmsi();
1500 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1501
1502 ptmsi2 = sgsn_alloc_ptmsi();
1503 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1504
1505 OSMO_ASSERT(ptmsi1 != ptmsi2);
1506
1507 printf(" - Repeated Attach Request\n");
1508
1509 /* reset the PRNG, so that the same P-TMSI will be generated
1510 * again */
1511 srand(1);
1512
1513 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1514
1515 /* Create a LLE/LLME */
1516 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1517 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1518 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1519
1520 /* inject the attach request */
1521 send_0408_message(lle->llme, foreign_tlli,
1522 attach_req, ARRAY_SIZE(attach_req));
1523
1524 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1525 OSMO_ASSERT(ctx != NULL);
1526 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1527 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1528
1529 old_ptmsi = ctx->p_tmsi_old;
1530
1531 /* we expect an identity request (IMEI) */
1532 OSMO_ASSERT(sgsn_tx_counter == 1);
1533
1534 /* inject the identity response (IMEI) */
1535 send_0408_message(ctx->llme, foreign_tlli,
1536 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1537
1538 /* check that the MM context has not been removed due to a failed
1539 * authorization */
1540 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1541
1542 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1543 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1544
1545 /* we expect an attach accept */
1546 OSMO_ASSERT(sgsn_tx_counter == 1);
1547
1548 /* we ignore this and send the attach again */
1549 send_0408_message(lle->llme, foreign_tlli,
1550 attach_req, ARRAY_SIZE(attach_req));
1551
1552 /* the allocated P-TMSI should be the same */
1553 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1554 OSMO_ASSERT(ctx != NULL);
1555 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1556 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1557 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1558
1559 /* inject the attach complete */
1560 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1561 send_0408_message(ctx->llme, local_tlli,
1562 attach_compl, ARRAY_SIZE(attach_compl));
1563
1564 /* we don't expect a response */
1565 OSMO_ASSERT(sgsn_tx_counter == 0);
1566
1567 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1568 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1569 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1570
1571 printf(" - Repeated RA Update Request\n");
1572
1573 /* inject the RA update request */
1574 send_0408_message(ctx->llme, local_tlli,
1575 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1576
1577 /* we expect an RA update accept */
1578 OSMO_ASSERT(sgsn_tx_counter == 1);
1579
1580 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1581 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1582 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1583
1584 /* repeat the RA update request */
1585 send_0408_message(ctx->llme, local_tlli,
1586 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1587
1588 /* we expect an RA update accept */
1589 OSMO_ASSERT(sgsn_tx_counter == 1);
1590
1591 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1592 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1593 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1594
1595 /* inject the RA update complete */
1596 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1597 send_0408_message(ctx->llme, local_tlli,
1598 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1599
1600 /* we don't expect a response */
1601 OSMO_ASSERT(sgsn_tx_counter == 0);
1602
1603 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1604 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1605 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1606
1607 /* inject the detach */
1608 send_0408_message(ctx->llme, local_tlli,
1609 detach_req, ARRAY_SIZE(detach_req));
1610
1611 /* verify that things are gone */
1612 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1613 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1614 OSMO_ASSERT(!ictx);
1615
1616 sgsn->cfg.auth_policy = saved_auth_policy;
1617}
1618
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001619static struct log_info_cat gprs_categories[] = {
1620 [DMM] = {
1621 .name = "DMM",
1622 .description = "Layer3 Mobility Management (MM)",
1623 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001624 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001625 },
1626 [DPAG] = {
1627 .name = "DPAG",
1628 .description = "Paging Subsystem",
1629 .color = "\033[1;38m",
1630 .enabled = 1, .loglevel = LOGL_NOTICE,
1631 },
1632 [DMEAS] = {
1633 .name = "DMEAS",
1634 .description = "Radio Measurement Processing",
1635 .enabled = 0, .loglevel = LOGL_NOTICE,
1636 },
1637 [DREF] = {
1638 .name = "DREF",
1639 .description = "Reference Counting",
1640 .enabled = 0, .loglevel = LOGL_NOTICE,
1641 },
1642 [DGPRS] = {
1643 .name = "DGPRS",
1644 .description = "GPRS Packet Service",
1645 .enabled = 1, .loglevel = LOGL_DEBUG,
1646 },
1647 [DNS] = {
1648 .name = "DNS",
1649 .description = "GPRS Network Service (NS)",
1650 .enabled = 1, .loglevel = LOGL_INFO,
1651 },
1652 [DBSSGP] = {
1653 .name = "DBSSGP",
1654 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1655 .enabled = 1, .loglevel = LOGL_DEBUG,
1656 },
1657 [DLLC] = {
1658 .name = "DLLC",
1659 .description = "GPRS Logical Link Control Protocol (LLC)",
1660 .enabled = 1, .loglevel = LOGL_DEBUG,
1661 },
1662 [DSNDCP] = {
1663 .name = "DSNDCP",
1664 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1665 .enabled = 1, .loglevel = LOGL_DEBUG,
1666 },
1667};
1668
1669static struct log_info info = {
1670 .cat = gprs_categories,
1671 .num_cat = ARRAY_SIZE(gprs_categories),
1672};
1673
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001674int main(int argc, char **argv)
1675{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001676 osmo_init_logging(&info);
1677 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
1678 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
1679
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01001680 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001681 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001682
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001683 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001684 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001685 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001686 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001687 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001688 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001689 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001690 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001691 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001692 test_gmm_attach_acl();
1693 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001694 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001695 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001696 test_gmm_attach_subscr_gsup_auth(0);
1697 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001698 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001699 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001700 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001701 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001702 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001703
1704 talloc_report_full(tall_bsc_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01001705 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001706 return 0;
1707}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001708
1709
1710/* stubs */
1711struct osmo_prim_hdr;
1712int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1713{
1714 abort();
1715}