blob: d55a0fc6a744321fd8d1047c86d339ff5fc53425 [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>
Jacob Erlbeck277b71e2015-02-02 18:03:05 +010029#include <openbsc/gprs_utils.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020030
Jacob Erlbeck189999d2014-10-27 14:34:13 +010031#include <osmocom/gprs/gprs_bssgp.h>
32
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020033#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeckbce20612015-01-05 18:57:32 +010034#include <openbsc/gsm_04_08_gprs.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020035
36#include <osmocom/core/application.h>
37#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010038#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020039
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020040#include <stdio.h>
41
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020042extern void *tall_msgb_ctx;
43
44void *tall_bsc_ctx;
45static struct sgsn_instance sgsn_inst = {
46 .config_file = "osmo_sgsn.cfg",
47 .cfg = {
48 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010049 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
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' */
Jacob Erlbeck555b2e52015-01-26 13:52:42 +010065void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
66void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010067 &__real_sgsn_update_subscriber_data;
68
Jacob Erlbeck555b2e52015-01-26 13:52:42 +010069void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010070{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +010071 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010072}
73
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010074/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
75int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
76int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
77 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010078
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010079int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
80 return (*subscr_request_update_location_cb)(mmctx);
81};
82
83/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
84int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
85int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
86 &__real_gprs_subscr_request_auth_info;
87
88int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
89 return (*subscr_request_auth_info_cb)(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +010090};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010091
Jacob Erlbeckc157ee72015-01-09 15:07:16 +010092/* override, requires '-Wl,--wrap=gprs_gsup_client_send' */
93int __real_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg);
94int (*gprs_gsup_client_send_cb)(struct gprs_gsup_client *gsupc, struct msgb *msg) =
95 &__real_gprs_gsup_client_send;
96
97int __wrap_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
98{
99 return (*gprs_gsup_client_send_cb)(gsupc, msg);
100};
101
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200102static int count(struct llist_head *head)
103{
104 struct llist_head *cur;
105 int count = 0;
106
107 llist_for_each(cur, head)
108 count += 1;
109
110 return count;
111}
112
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200113static struct msgb *create_msg(const uint8_t *data, size_t len)
114{
115 struct msgb *msg = msgb_alloc(len + 8, "test message");
116 msg->l1h = msgb_put(msg, 8);
117 msg->l2h = msgb_put(msg, len);
118 memcpy(msg->l2h, data, len);
119
120 msgb_bcid(msg) = msg->l1h;
121 msgb_gmmh(msg) = msg->l2h;
122 return msg;
123}
124
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100125/*
126 * Create a context and search for it
127 */
128static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
129{
130 struct sgsn_mm_ctx *ctx, *ictx;
131 struct gprs_llc_lle *lle;
132 int old_count = count(gprs_llme_list());
133
134 lle = gprs_lle_get_or_create(tlli, 3);
135 ctx = sgsn_mm_ctx_alloc(tlli, raid);
136 ctx->mm_state = GMM_REGISTERED_NORMAL;
137 ctx->llme = lle->llme;
138
139 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
140 OSMO_ASSERT(ictx == ctx);
141
142 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
143
144 return ctx;
145}
146
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100147static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
148 const uint8_t *data, size_t data_len)
149{
150 struct msgb *msg;
151
152 sgsn_tx_counter = 0;
153
154 msg = create_msg(data, data_len);
155 msgb_tlli(msg) = tlli;
156 gsm0408_gprs_rcvmsg(msg, llme);
157 msgb_free(msg);
158}
159
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200160static void test_llme(void)
161{
162 struct gprs_llc_lle *lle, *lle_copy;
163 uint32_t local_tlli;
164 uint32_t foreign_tlli;
165
166 printf("Testing LLME allocations\n");
167 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
168 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
169
170 /* initial state */
171 OSMO_ASSERT(count(gprs_llme_list()) == 0);
172
173 /* Create a new entry */
174 lle = gprs_lle_get_or_create(local_tlli, 3);
175 OSMO_ASSERT(lle);
176 OSMO_ASSERT(count(gprs_llme_list()) == 1);
177
178 /* No new entry is created */
179 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
180 OSMO_ASSERT(lle == lle_copy);
181 OSMO_ASSERT(count(gprs_llme_list()) == 1);
182 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
183 OSMO_ASSERT(lle == lle_copy);
184 OSMO_ASSERT(count(gprs_llme_list()) == 1);
185
186 /* unassign which should delete it*/
187 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
188
189 /* Check that everything was cleaned up */
190 OSMO_ASSERT(count(gprs_llme_list()) == 0);
191}
192
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100193struct gsm_subscriber *last_updated_subscr = NULL;
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100194void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100195{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100196 OSMO_ASSERT(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100197 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100198 __func__, mmctx, mmctx->subscr);
199 last_updated_subscr = mmctx->subscr;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100200}
201
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100202static void assert_subscr(const struct gsm_subscriber *subscr, const char *imsi)
203{
204 struct gsm_subscriber *sfound;
Jacob Erlbeck6be9ffa2015-01-19 08:57:07 +0100205 OSMO_ASSERT(subscr);
206 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100207
208 sfound = gprs_subscr_get_by_imsi(imsi);
209 OSMO_ASSERT(sfound == subscr);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100210
Jacob Erlbeck6be9ffa2015-01-19 08:57:07 +0100211 subscr_put(sfound);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100212}
213
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100214static void show_subscrs(FILE *out)
215{
216 struct gsm_subscriber *subscr;
217
218 llist_for_each_entry(subscr, &active_subscribers, entry) {
219 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100220 "use count: %d\n",
221 subscr->imsi, subscr->use_count);
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100222 }
223}
224
225static void assert_no_subscrs()
226{
227 show_subscrs(stdout);
228 fflush(stdout);
229 OSMO_ASSERT(llist_empty(&active_subscribers));
230}
231
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100232static void test_subscriber(void)
233{
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100234 struct gsm_subscriber *s1, *s2, *s3, *sfound;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100235 const char *imsi1 = "1234567890";
236 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100237 const char *imsi3 = "5656565656";
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100238
239 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
240
241 printf("Testing core subscriber data API\n");
242
243 /* Check for emptiness */
244 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
245 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100246 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100247
248 /* Allocate entry 1 */
249 s1 = gprs_subscr_get_or_create(imsi1);
250 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100251 assert_subscr(s1, imsi1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100252 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100253
254 /* Allocate entry 2 */
255 s2 = gprs_subscr_get_or_create(imsi2);
256 s2->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100257
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100258 /* Allocate entry 3 */
259 s3 = gprs_subscr_get_or_create(imsi3);
260
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100261 /* Check entries */
262 assert_subscr(s1, imsi1);
263 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100264 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100265
266 /* Update entry 1 */
267 last_updated_subscr = NULL;
268 gprs_subscr_update(s1);
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100269 OSMO_ASSERT(last_updated_subscr == NULL);
270 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
271 OSMO_ASSERT((s1->flags & GSM_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100272
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100273 /* There is no subscriber cache. Verify it */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100274 gprs_subscr_cleanup(s1);
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100275 subscr_put(s1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100276 s1 = NULL;
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100277 sfound = gprs_subscr_get_by_imsi(imsi1);
278 OSMO_ASSERT(sfound == NULL);
279
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100280 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100281 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100282
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100283 /* Free entry 2 (GSM_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100284 gprs_subscr_cleanup(s2);
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100285 subscr_put(s2);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100286 s2 = NULL;
287 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
288 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100289 assert_subscr(s3, imsi3);
290
291 /* Try to delete entry 3 */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100292 gprs_subscr_cleanup(s3);
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100293 subscr_put(s3);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100294 s3 = NULL;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100295 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100296
297 OSMO_ASSERT(llist_empty(&active_subscribers));
298
299 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
300}
301
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100302static void test_auth_triplets(void)
303{
304 struct gsm_subscriber *s1, *s1found;
305 const char *imsi1 = "1234567890";
306 struct gsm_auth_tuple *at;
307 struct sgsn_mm_ctx *ctx;
308 struct gprs_ra_id raid = { 0, };
309 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100310
311 printf("Testing authentication triplet handling\n");
312
313 /* Check for emptiness */
314 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
315
316 /* Allocate entry 1 */
317 s1 = gprs_subscr_get_or_create(imsi1);
318 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
319 s1found = gprs_subscr_get_by_imsi(imsi1);
320 OSMO_ASSERT(s1found == s1);
321 subscr_put(s1found);
322
323 /* Create a context */
324 OSMO_ASSERT(count(gprs_llme_list()) == 0);
325 ctx = alloc_mm_ctx(local_tlli, &raid);
326
327 /* Attach s1 to ctx */
328 ctx->subscr = subscr_get(s1);
329 ctx->subscr->sgsn_data->mm = ctx;
330
331 /* Try to get auth tuple */
332 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
333 OSMO_ASSERT(at == NULL);
334
335 /* Add triplets */
336 s1->sgsn_data->auth_triplets[0].key_seq = 0;
337 s1->sgsn_data->auth_triplets[1].key_seq = 1;
338 s1->sgsn_data->auth_triplets[2].key_seq = 2;
339
340 /* Try to get auth tuple */
341 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
342 OSMO_ASSERT(at != NULL);
343 OSMO_ASSERT(at->key_seq == 0);
344 OSMO_ASSERT(at->use_count == 1);
345 at = sgsn_auth_get_tuple(ctx, at->key_seq);
346 OSMO_ASSERT(at != NULL);
347 OSMO_ASSERT(at->key_seq == 1);
348 OSMO_ASSERT(at->use_count == 1);
349 at = sgsn_auth_get_tuple(ctx, at->key_seq);
350 OSMO_ASSERT(at != NULL);
351 OSMO_ASSERT(at->key_seq == 2);
352 OSMO_ASSERT(at->use_count == 1);
353 at = sgsn_auth_get_tuple(ctx, at->key_seq);
354 OSMO_ASSERT(at == NULL);
355
356 /* Free MM context and subscriber */
357 subscr_put(s1);
Jacob Erlbecke671d252015-01-26 14:43:07 +0100358 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100359 s1found = gprs_subscr_get_by_imsi(imsi1);
360 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100361}
362
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100363#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
364
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100365static int rx_gsup_message(const uint8_t *data, size_t data_len)
366{
367 struct msgb *msg;
368 int rc;
369
370 msg = msgb_alloc(1024, __func__);
371 msg->l2h = msgb_put(msg, data_len);
372 OSMO_ASSERT(msg->l2h != NULL);
373 memcpy(msg->l2h, data, data_len);
374 rc = gprs_subscr_rx_gsup_message(msg);
375 msgb_free(msg);
376
377 return rc;
378}
379
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100380static void test_subscriber_gsup(void)
381{
382 struct gsm_subscriber *s1, *s1found;
383 const char *imsi1 = "1234567890";
384 struct sgsn_mm_ctx *ctx;
385 struct gprs_ra_id raid = { 0, };
386 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100387 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100388 int rc;
389
390 static const uint8_t send_auth_info_res[] = {
391 0x0a,
392 TEST_GSUP_IMSI1_IE,
393 0x03, 0x22, /* Auth tuple */
394 0x20, 0x10,
395 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
396 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
397 0x21, 0x04,
398 0x21, 0x22, 0x23, 0x24,
399 0x22, 0x08,
400 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
401 0x03, 0x22, /* Auth tuple */
402 0x20, 0x10,
403 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
404 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
405 0x21, 0x04,
406 0xa1, 0xa2, 0xa3, 0xa4,
407 0x22, 0x08,
408 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
409 };
410
411 static const uint8_t send_auth_info_err[] = {
412 0x09,
413 TEST_GSUP_IMSI1_IE,
414 0x02, 0x01, 0x07 /* GPRS not allowed */
415 };
416
417 static const uint8_t update_location_res[] = {
418 0x06,
419 TEST_GSUP_IMSI1_IE,
420 0x04, 0x00, /* PDP info complete */
421 0x05, 0x12,
422 0x10, 0x01, 0x01,
423 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
424 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
425 0x05, 0x11,
426 0x10, 0x01, 0x02,
427 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
428 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
429 };
430
431 static const uint8_t update_location_err[] = {
432 0x05,
433 TEST_GSUP_IMSI1_IE,
434 0x02, 0x01, 0x07 /* GPRS not allowed */
435 };
436
437 static const uint8_t location_cancellation_req[] = {
438 0x1c,
439 TEST_GSUP_IMSI1_IE,
440 0x06, 0x01, 0x00,
441 };
442
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100443 static const uint8_t location_cancellation_req_other[] = {
444 0x1c,
445 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
446 0x06, 0x01, 0x00,
447 };
448
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100449 static const uint8_t purge_ms_err[] = {
450 0x0d,
451 TEST_GSUP_IMSI1_IE,
452 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
453 };
454
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100455 static const uint8_t purge_ms_err_no_cause[] = {
456 0x0d,
457 TEST_GSUP_IMSI1_IE,
458 };
459
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100460 static const uint8_t purge_ms_res[] = {
461 0x0e,
462 TEST_GSUP_IMSI1_IE,
463 0x07, 0x00,
464 };
465
466
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100467 static const uint8_t insert_data_req[] = {
468 0x10,
469 TEST_GSUP_IMSI1_IE,
470 0x05, 0x11,
471 0x10, 0x01, 0x03,
472 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
473 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
474 };
475
476 static const uint8_t delete_data_req[] = {
477 0x14,
478 TEST_GSUP_IMSI1_IE,
479 0x10, 0x01, 0x03,
480 };
481
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100482 printf("Testing subcriber GSUP handling\n");
483
484 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
485
486 /* Check for emptiness */
487 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
488
489 /* Allocate entry 1 */
490 s1 = gprs_subscr_get_or_create(imsi1);
491 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
492 s1found = gprs_subscr_get_by_imsi(imsi1);
493 OSMO_ASSERT(s1found == s1);
494 subscr_put(s1found);
495
496 /* Create a context */
497 OSMO_ASSERT(count(gprs_llme_list()) == 0);
498 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100499
500 /* Attach s1 to ctx */
501 ctx->subscr = subscr_get(s1);
502 ctx->subscr->sgsn_data->mm = ctx;
503
504 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100505 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100506 OSMO_ASSERT(rc >= 0);
507 OSMO_ASSERT(last_updated_subscr == s1);
508
509 /* Check triplets */
510 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
511 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
512 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
513
514 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100515 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100516 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100517 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100518 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100519
520 /* Check triplets */
521 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
522 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
523 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
524
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100525 /* Inject UpdateLocRes GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100526 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100527 OSMO_ASSERT(rc >= 0);
528 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100529 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100530 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100531 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
532 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
533 struct sgsn_subscriber_pdp_data, list);
534 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
535 pdpd = llist_entry(pdpd->list.next,
536 struct sgsn_subscriber_pdp_data, list);
537 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100538
539 /* Check authorization */
540 OSMO_ASSERT(s1->authorized == 1);
541
542 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100543 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100544 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100545 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100546 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100547
548 /* Check authorization */
549 OSMO_ASSERT(s1->authorized == 0);
550
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100551 /* Inject InsertSubscrData GSUP message */
552 last_updated_subscr = NULL;
553 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
554 OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
555 OSMO_ASSERT(last_updated_subscr == NULL);
556
557 /* Inject DeleteSubscrData GSUP message */
558 last_updated_subscr = NULL;
559 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
560 OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
561 OSMO_ASSERT(last_updated_subscr == NULL);
562
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100563 /* Inject wrong LocCancelReq GSUP message */
564 last_updated_subscr = NULL;
565 rc = rx_gsup_message(location_cancellation_req_other,
566 sizeof(location_cancellation_req_other));
567 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
568 OSMO_ASSERT(last_updated_subscr == NULL);
569
570 /* Check cancellation result */
571 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
572 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
573
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100574 /* Inject LocCancelReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100575 rc = rx_gsup_message(location_cancellation_req,
576 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100577 OSMO_ASSERT(rc >= 0);
578 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100579 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100580
581 /* Check cancellation result */
582 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
583 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
584
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100585 /* Inject PurgeMsRes GSUP message */
586 rc = rx_gsup_message(purge_ms_res,
587 sizeof(purge_ms_res));
588 OSMO_ASSERT(rc >= 0);
589 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
590
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100591 /* Free MM context and subscriber */
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +0100592 OSMO_ASSERT(ctx->subscr == NULL);
593 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100594 subscr_put(s1);
595 s1found = gprs_subscr_get_by_imsi(imsi1);
596 OSMO_ASSERT(s1found == NULL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100597
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100598 /* Inject PurgeMsRes GSUP message */
599 rc = rx_gsup_message(purge_ms_res,
600 sizeof(purge_ms_res));
601 OSMO_ASSERT(rc >= 0);
602
603 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
604 rc = rx_gsup_message(purge_ms_err,
605 sizeof(purge_ms_err));
606 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
607
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100608 /* Inject PurgeMsErr() GSUP message */
609 rc = rx_gsup_message(purge_ms_err_no_cause,
610 sizeof(purge_ms_err_no_cause));
611 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
612
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100613 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
614 last_updated_subscr = NULL;
615 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100616 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100617 OSMO_ASSERT(last_updated_subscr == NULL);
618
619 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
620 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
621 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
622 OSMO_ASSERT(last_updated_subscr == NULL);
623
624 /* Inject LocCancelReq GSUP message (unknown IMSI) */
625 rc = rx_gsup_message(location_cancellation_req,
626 sizeof(location_cancellation_req));
627 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
628 OSMO_ASSERT(last_updated_subscr == NULL);
629
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100630 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
631}
632
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100633int my_gprs_gsup_client_send_dummy(struct gprs_gsup_client *gsupc, struct msgb *msg)
634{
635 msgb_free(msg);
636 return 0;
637};
638
639
640static void test_subscriber_blocking(void)
641{
642 struct gsm_subscriber *s1;
643 const char *imsi1 = "1234567890";
644 struct sgsn_mm_ctx *ctx;
645 struct gprs_ra_id raid = { 0, };
646 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100647 int rc;
648
649 printf("Testing subcriber procedure blocking\n");
650
651 gprs_gsup_client_send_cb = my_gprs_gsup_client_send_dummy;
652 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
653
654 /* Check for emptiness */
655 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
656
657 /* Create a context */
658 OSMO_ASSERT(count(gprs_llme_list()) == 0);
659 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100660 strncpy(ctx->imsi, imsi1, sizeof(ctx->imsi) - 1);
661
662 /* Allocate and attach a subscriber */
663 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
664 assert_subscr(s1, imsi1);
665
666 /* Start SendAuthInfoRequest procedure */
667 rc = gprs_subscr_query_auth_info(s1);
668 /* Not blocking */
669 OSMO_ASSERT(rc == 0);
670
671 /* Start UpdateLocation procedure */
672 rc = gprs_subscr_location_update(s1);
673 /* Blocking */
674 OSMO_ASSERT(rc == 0);
675
676 /* Start PurgeMS procedure */
677 rc = gprs_subscr_purge(s1);
678 /* Not blocking */
679 OSMO_ASSERT(rc == 0);
680 OSMO_ASSERT(s1->sgsn_data->blocked_by == SGSN_SUBSCR_PROC_PURGE);
681
682 /* Start PurgeMS procedure (retry) */
683 rc = gprs_subscr_purge(s1);
684 /* Not blocking */
685 OSMO_ASSERT(rc == 0);
686
687 /* Start SendAuthInfoRequest procedure */
688 rc = gprs_subscr_query_auth_info(s1);
689 /* Blocking */
690 OSMO_ASSERT(rc == -EAGAIN);
691
692 /* Start UpdateLocation procedure */
693 rc = gprs_subscr_location_update(s1);
694 /* Blocking */
695 OSMO_ASSERT(rc == -EAGAIN);
696
697 /* Unblock manually (normally done by the caller of gprs_subscr_purge) */
698 s1->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
699
700 /* Start SendAuthInfoRequest procedure */
701 rc = gprs_subscr_query_auth_info(s1);
702 /* Not blocking */
703 OSMO_ASSERT(rc == 0);
704
705 /* Start UpdateLocation procedure */
706 rc = gprs_subscr_location_update(s1);
707 /* Blocking */
708 OSMO_ASSERT(rc == 0);
709
710 subscr_put(s1);
Jacob Erlbecke671d252015-01-26 14:43:07 +0100711 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100712
713 assert_no_subscrs();
714
715 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
716 talloc_free(sgsn->gsup_client);
717 sgsn->gsup_client = NULL;
718}
719
720
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200721/*
722 * Test that a GMM Detach will remove the MMCTX and the
723 * associated LLME.
724 */
725static void test_gmm_detach(void)
726{
727 struct gprs_ra_id raid = { 0, };
728 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200729 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200730
731 printf("Testing GMM detach\n");
732
733 /* DTAP - Detach Request (MO) */
734 /* normal detach, power_off = 0 */
735 static const unsigned char detach_req[] = {
736 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
737 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
738 };
739
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200740 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200741
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100742 /* Create a context */
743 OSMO_ASSERT(count(gprs_llme_list()) == 0);
744 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200745
746 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100747 send_0408_message(ctx->llme, local_tlli,
748 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200749
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100750 /* verify that a single message (hopefully the Detach Accept) has been
751 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100752 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100753
754 /* verify that things are gone */
755 OSMO_ASSERT(count(gprs_llme_list()) == 0);
756 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
757 OSMO_ASSERT(!ictx);
758}
759
760/*
761 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
762 * will not sent a Detach Accept message (power_off = 1)
763 */
764static void test_gmm_detach_power_off(void)
765{
766 struct gprs_ra_id raid = { 0, };
767 struct sgsn_mm_ctx *ctx, *ictx;
768 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100769
770 printf("Testing GMM detach (power off)\n");
771
772 /* DTAP - Detach Request (MO) */
773 /* normal detach, power_off = 1 */
774 static const unsigned char detach_req[] = {
775 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
776 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
777 };
778
779 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
780
781 /* Create a context */
782 OSMO_ASSERT(count(gprs_llme_list()) == 0);
783 ctx = alloc_mm_ctx(local_tlli, &raid);
784
785 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100786 send_0408_message(ctx->llme, local_tlli,
787 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100788
789 /* verify that no message (and therefore no Detach Accept) has been
790 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100791 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100792
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200793 /* verify that things are gone */
794 OSMO_ASSERT(count(gprs_llme_list()) == 0);
795 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200796 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200797}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200798
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200799/*
800 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
801 */
802static void test_gmm_detach_no_mmctx(void)
803{
804 struct gprs_llc_lle *lle;
805 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200806
807 printf("Testing GMM detach (no MMCTX)\n");
808
809 /* DTAP - Detach Request (MO) */
810 /* normal detach, power_off = 0 */
811 static const unsigned char detach_req[] = {
812 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
813 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
814 };
815
816 /* Create an LLME */
817 OSMO_ASSERT(count(gprs_llme_list()) == 0);
818 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
819 lle = gprs_lle_get_or_create(local_tlli, 3);
820
821 OSMO_ASSERT(count(gprs_llme_list()) == 1);
822
823 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100824 send_0408_message(lle->llme, local_tlli,
825 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200826
827 /* verify that the LLME is gone */
828 OSMO_ASSERT(count(gprs_llme_list()) == 0);
829}
830
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100831/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100832 * Test that a single GMM Detach Accept message will not cause the SGSN to send
833 * any message or leave an MM context at the SGSN.
834 */
835static void test_gmm_detach_accept_unexpected(void)
836{
837 struct gprs_llc_lle *lle;
838 uint32_t local_tlli;
839
840 printf("Testing GMM detach accept (unexpected)\n");
841
842 /* DTAP - Detach Accept (MT) */
843 /* normal detach */
844 static const unsigned char detach_acc[] = {
845 0x08, 0x06
846 };
847
848 /* Create an LLME */
849 OSMO_ASSERT(count(gprs_llme_list()) == 0);
850 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
851 lle = gprs_lle_get_or_create(local_tlli, 3);
852
853 /* inject the detach */
854 send_0408_message(lle->llme, local_tlli,
855 detach_acc, ARRAY_SIZE(detach_acc));
856
857 /* verify that no message (and therefore no Status or XID reset) has been
858 * sent by the SGSN */
859 OSMO_ASSERT(sgsn_tx_counter == 0);
860
861 /* verify that things are gone */
862 OSMO_ASSERT(count(gprs_llme_list()) == 0);
863}
864
865/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100866 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
867 */
868static void test_gmm_status_no_mmctx(void)
869{
870 struct gprs_llc_lle *lle;
871 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100872
873 printf("Testing GMM Status (no MMCTX)\n");
874
875 /* DTAP - GMM Status, protocol error */
876 static const unsigned char gmm_status[] = {
877 0x08, 0x20, 0x6f
878 };
879
880 /* Create an LLME */
881 OSMO_ASSERT(count(gprs_llme_list()) == 0);
882 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
883 lle = gprs_lle_get_or_create(local_tlli, 3);
884
885 OSMO_ASSERT(count(gprs_llme_list()) == 1);
886
887 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100888 send_0408_message(lle->llme, local_tlli,
889 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100890
891 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100892 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100893
894 /* verify that the LLME is gone */
895 OSMO_ASSERT(count(gprs_llme_list()) == 0);
896}
897
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100898/*
899 * Test the GMM Attach procedure
900 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100901static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100902{
903 struct gprs_ra_id raid = { 0, };
904 struct sgsn_mm_ctx *ctx = NULL;
905 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100906 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100907 uint32_t foreign_tlli;
908 uint32_t local_tlli = 0;
909 struct gprs_llc_lle *lle;
910
911 /* DTAP - Attach Request */
912 /* The P-TMSI is not known by the SGSN */
913 static const unsigned char attach_req[] = {
914 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
915 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
916 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
917 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
918 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
919 };
920
921 /* DTAP - Identity Response IMEI */
922 static const unsigned char ident_resp_imei[] = {
923 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
924 0x56
925 };
926
927 /* DTAP - Identity Response IMSI */
928 static const unsigned char ident_resp_imsi[] = {
929 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
930 0x54
931 };
932
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100933 /* DTAP - Authentication and Ciphering Resp */
934 static const unsigned char auth_ciph_resp[] = {
935 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
936 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
937 };
938
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100939 /* DTAP - Attach Complete */
940 static const unsigned char attach_compl[] = {
941 0x08, 0x03
942 };
943
944 /* DTAP - Detach Request (MO) */
945 /* normal detach, power_off = 0 */
946 static const unsigned char detach_req[] = {
947 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
948 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
949 };
950
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100951 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100952
953 /* reset the PRNG used by sgsn_alloc_ptmsi */
954 srand(1);
955
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100956 ptmsi1 = sgsn_alloc_ptmsi();
957 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
958
959 /* reset the PRNG, so that the same P-TMSI sequence will be generated
960 * again */
961 srand(1);
962
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100963 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
964
965 /* Create a LLE/LLME */
966 OSMO_ASSERT(count(gprs_llme_list()) == 0);
967 lle = gprs_lle_get_or_create(foreign_tlli, 3);
968 OSMO_ASSERT(count(gprs_llme_list()) == 1);
969
970 /* inject the attach request */
971 send_0408_message(lle->llme, foreign_tlli,
972 attach_req, ARRAY_SIZE(attach_req));
973
974 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
975 OSMO_ASSERT(ctx != NULL);
976 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
977
978 /* we expect an identity request (IMEI) */
979 OSMO_ASSERT(sgsn_tx_counter == 1);
980
981 /* inject the identity response (IMEI) */
982 send_0408_message(ctx->llme, foreign_tlli,
983 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
984
985 /* we expect an identity request (IMSI) */
986 OSMO_ASSERT(sgsn_tx_counter == 1);
987
988 /* inject the identity response (IMSI) */
989 send_0408_message(ctx->llme, foreign_tlli,
990 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
991
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100992 /* check that the MM context has not been removed due to a failed
993 * authorization */
994 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
995
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100996 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100997
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100998retry_attach_req:
999
1000 if (retry && sgsn_tx_counter == 0) {
1001 fprintf(stderr, "Retrying attach request\n");
1002 /* re-inject the attach request */
1003 send_0408_message(lle->llme, foreign_tlli,
1004 attach_req, ARRAY_SIZE(attach_req));
1005 }
1006
1007 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
1008 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001009
1010 /* inject the auth & ciph response */
1011 send_0408_message(ctx->llme, foreign_tlli,
1012 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
1013
1014 /* check that the MM context has not been removed due to a
1015 * failed authorization */
1016 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1017 }
1018
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001019 if (retry && sgsn_tx_counter == 0)
1020 goto retry_attach_req;
1021
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001022 /* we expect an attach accept/reject */
1023 OSMO_ASSERT(sgsn_tx_counter == 1);
1024
1025 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +01001026 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001027
1028 /* inject the attach complete */
1029 send_0408_message(ctx->llme, local_tlli,
1030 attach_compl, ARRAY_SIZE(attach_compl));
1031
1032 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1033
1034 /* we don't expect a response */
1035 OSMO_ASSERT(sgsn_tx_counter == 0);
1036
1037 /* inject the detach */
1038 send_0408_message(ctx->llme, local_tlli,
1039 detach_req, ARRAY_SIZE(detach_req));
1040
1041 /* verify that things are gone */
1042 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1043 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1044 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001045}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +01001046
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001047static void test_gmm_attach_acl(void)
1048{
1049 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1050
1051 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
1052 sgsn_acl_add("123456789012345", &sgsn->cfg);
1053 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001054 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +01001055 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001056
1057 sgsn->cfg.auth_policy = saved_auth_policy;
1058}
1059
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001060int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001061 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001062 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001063 if (rc == -ENOTSUP) {
1064 OSMO_ASSERT(mmctx->subscr);
1065 gprs_subscr_update(mmctx->subscr);
1066 }
1067 return rc;
1068};
1069
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001070int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
1071 gprs_subscr_update(mmctx->subscr);
1072 return 0;
1073};
1074
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001075static void test_gmm_attach_subscr(void)
1076{
1077 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1078 struct gsm_subscriber *subscr;
1079
1080 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001081 subscr_request_update_location_cb = my_subscr_request_update_location;
1082 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001083
1084 subscr = gprs_subscr_get_or_create("123456789012345");
1085 subscr->authorized = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001086
1087 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001088 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001089 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001090 assert_no_subscrs();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001091
1092 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001093 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1094 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001095}
1096
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001097int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
1098{
1099 /* Fake an authentication */
1100 OSMO_ASSERT(mmctx->subscr);
1101 mmctx->is_authenticated = 1;
1102 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001103
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001104 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001105};
1106
1107static void test_gmm_attach_subscr_fake_auth(void)
1108{
1109 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1110 struct gsm_subscriber *subscr;
1111
1112 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001113 subscr_request_update_location_cb = my_subscr_request_update_location;
1114 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001115
1116 subscr = gprs_subscr_get_or_create("123456789012345");
1117 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001118 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001119 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001120
1121 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001122 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001123 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001124 assert_no_subscrs();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001125
1126 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001127 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1128 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
1129}
1130
1131int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
1132{
1133 struct gsm_auth_tuple at = {
1134 .sres = {0x51, 0xe5, 0x51, 0xe5},
1135 .key_seq = 0
1136 };
1137
1138 /* Fake an authentication */
1139 OSMO_ASSERT(mmctx->subscr);
1140 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
1141
1142 gprs_subscr_update_auth_info(mmctx->subscr);
1143
1144 return 0;
1145};
1146
1147static void test_gmm_attach_subscr_real_auth(void)
1148{
1149 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1150 struct gsm_subscriber *subscr;
1151
1152 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1153 subscr_request_update_location_cb = my_subscr_request_update_location;
1154 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
1155
1156 subscr = gprs_subscr_get_or_create("123456789012345");
1157 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001158 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001159 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001160
1161 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001162
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001163 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001164 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001165 assert_no_subscrs();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001166
1167 sgsn->cfg.auth_policy = saved_auth_policy;
1168 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1169 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001170}
1171
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001172#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
1173 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
1174
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001175static int auth_info_skip = 0;
1176static int upd_loc_skip = 0;
1177
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001178int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
1179{
1180 static const uint8_t send_auth_info_res[] = {
1181 0x0a,
1182 TEST_GSUP_IMSI_LONG_IE,
1183 0x03, 0x22, /* Auth tuple */
1184 0x20, 0x10,
1185 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1186 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1187 0x21, 0x04,
1188 0x51, 0xe5, 0x51, 0xe5,
1189 0x22, 0x08,
1190 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1191 };
1192
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001193 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001194
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001195 if (auth_info_skip > 0) {
1196 auth_info_skip -= 1;
1197 return -EAGAIN;
1198 }
1199
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001200 /* Fake an SendAuthInfoRes */
1201 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1202
1203 return 0;
1204};
1205
1206int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1207 static const uint8_t update_location_res[] = {
1208 0x06,
1209 TEST_GSUP_IMSI_LONG_IE,
1210 0x04, 0x00, /* PDP info complete */
1211 0x05, 0x12,
1212 0x10, 0x01, 0x01,
1213 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1214 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
1215 };
1216
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001217 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001218
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001219 if (upd_loc_skip > 0) {
1220 upd_loc_skip -= 1;
1221 return -EAGAIN;
1222 }
1223
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001224 /* Fake an UpdateLocRes */
1225 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1226};
1227
1228
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001229static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001230{
1231 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1232 struct gsm_subscriber *subscr;
1233
1234 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1235 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1236 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001237 if (retry) {
1238 upd_loc_skip = 3;
1239 auth_info_skip = 3;
1240 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001241
1242 subscr = gprs_subscr_get_or_create("123456789012345");
1243 subscr->authorized = 1;
1244 sgsn->cfg.require_authentication = 1;
1245 sgsn->cfg.require_update_location = 1;
1246 subscr_put(subscr);
1247
1248 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001249 test_gmm_attach(retry);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001250 assert_no_subscrs();
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001251
1252 sgsn->cfg.auth_policy = saved_auth_policy;
1253 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1254 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001255 upd_loc_skip = 0;
1256 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001257}
1258
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001259int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1260{
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001261 struct gprs_gsup_message to_peer = {0};
1262 struct gprs_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001263 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001264 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001265
1266 /* Simulate the GSUP peer */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001267 rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1268 OSMO_ASSERT(rc >= 0);
1269 OSMO_ASSERT(to_peer.imsi[0] != 0);
1270 strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001271
1272 /* This invalidates the pointers in to_peer */
1273 msgb_free(msg);
1274
1275 switch (to_peer.message_type) {
1276 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1277 /* Send UPDATE_LOCATION_RESULT */
1278 return my_subscr_request_update_gsup_auth(NULL);
1279
1280 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1281 /* Send SEND_AUTH_INFO_RESULT */
1282 return my_subscr_request_auth_info_gsup_auth(NULL);
1283
1284 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001285 from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
1286 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001287
1288 default:
1289 if ((to_peer.message_type & 0b00000011) == 0) {
1290 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001291 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001292 from_peer.message_type = to_peer.message_type + 1;
1293 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1294 break;
1295 }
1296
1297 /* Ignore it */
1298 return 0;
1299 }
1300
1301 reply_msg = gprs_gsup_msgb_alloc();
1302 reply_msg->l2h = reply_msg->data;
1303 gprs_gsup_encode(reply_msg, &from_peer);
1304 gprs_subscr_rx_gsup_message(reply_msg);
1305 msgb_free(reply_msg);
1306
1307 return 0;
1308};
1309
1310static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1311{
1312 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1313 struct gsm_subscriber *subscr;
1314
1315 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001316 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1317
1318 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1319
1320 if (retry) {
1321 upd_loc_skip = 3;
1322 auth_info_skip = 3;
1323 }
1324
1325 printf("Auth policy 'remote', real GSUP based auth: ");
1326 test_gmm_attach(retry);
1327
1328 subscr = gprs_subscr_get_by_imsi("123456789012345");
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001329 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001330 assert_no_subscrs();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001331
1332 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001333 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1334 upd_loc_skip = 0;
1335 auth_info_skip = 0;
1336 talloc_free(sgsn->gsup_client);
1337 sgsn->gsup_client = NULL;
1338}
1339
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001340/*
1341 * Test the GMM Rejects
1342 */
1343static void test_gmm_reject(void)
1344{
1345 struct gprs_ra_id raid = { 0, };
1346 struct sgsn_mm_ctx *ctx = NULL;
1347 uint32_t foreign_tlli;
1348 struct gprs_llc_lle *lle;
1349 int idx;
1350
1351 /* DTAP - Attach Request */
1352 /* Invalid MI length */
1353 static const unsigned char attach_req_inv_mi_len[] = {
1354 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1355 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1356 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1357 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1358 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1359 };
1360
1361 /* DTAP - Attach Request */
1362 /* Invalid MI type (IMEI) */
1363 static const unsigned char attach_req_inv_mi_type[] = {
1364 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1365 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1366 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1367 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1368 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1369 };
1370
1371 /* DTAP - Routing Area Update Request */
1372 static const unsigned char dtap_ra_upd_req[] = {
1373 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1374 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1375 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1376 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1377 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1378 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1379 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1380 };
1381
1382 /* DTAP - Routing Area Update Request */
1383 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1384 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1385 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1386 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1387 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1388 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1389 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1390 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1391 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1392 };
1393
1394 /* DTAP - Routing Area Update Request */
1395 /* Invalid cap length */
1396 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1397 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1398 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1399 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1400 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1401 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1402 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1403 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1404 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1405 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1406 };
1407
1408 struct test {
1409 const char *title;
1410 const unsigned char *msg;
1411 unsigned msg_len;
1412 unsigned num_resp;
1413
1414 };
1415 static struct test tests[] = {
1416 {
1417 .title = "Attach Request (invalid MI length)",
1418 .msg = attach_req_inv_mi_len,
1419 .msg_len = sizeof(attach_req_inv_mi_len),
1420 .num_resp = 1 /* Reject */
1421
1422 },
1423 {
1424 .title = "Attach Request (invalid MI type)",
1425 .msg = attach_req_inv_mi_type,
1426 .msg_len = sizeof(attach_req_inv_mi_type),
1427 .num_resp = 1 /* Reject */
1428 },
1429 {
1430 .title = "Routing Area Update Request (valid)",
1431 .msg = dtap_ra_upd_req,
1432 .msg_len = sizeof(dtap_ra_upd_req),
1433 .num_resp = 2 /* XID Reset + Reject */
1434 },
1435 {
1436 .title = "Routing Area Update Request (invalid type)",
1437 .msg = dtap_ra_upd_req_inv_type,
1438 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1439 .num_resp = 1 /* Reject */
1440 },
1441 {
1442 .title = "Routing Area Update Request (invalid CAP length)",
1443 .msg = dtap_ra_upd_req_inv_cap_len,
1444 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1445 .num_resp = 1 /* Reject */
1446 },
1447 };
1448
1449 printf("Testing GMM reject\n");
1450
1451 /* reset the PRNG used by sgsn_alloc_ptmsi */
1452 srand(1);
1453
1454 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1455
1456 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1457
1458 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1459 const struct test *test = &tests[idx];
1460 printf(" - %s\n", test->title);
1461
1462 /* Create a LLE/LLME */
1463 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1464 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1465
1466 /* Inject the Request message */
1467 send_0408_message(lle->llme, foreign_tlli,
1468 test->msg, test->msg_len);
1469
1470 /* We expect a Reject message */
1471 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1472 sgsn_tx_counter, test->num_resp);
1473 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1474
1475 /* verify that LLME/MM are removed */
1476 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1477 OSMO_ASSERT(ctx == NULL);
1478 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1479 }
1480}
1481
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001482/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001483 * Test cancellation of attached MM contexts
1484 */
1485static void test_gmm_cancel(void)
1486{
1487 struct gprs_ra_id raid = { 0, };
1488 struct sgsn_mm_ctx *ctx = NULL;
1489 struct sgsn_mm_ctx *ictx;
1490 uint32_t ptmsi1;
1491 uint32_t foreign_tlli;
1492 uint32_t local_tlli = 0;
1493 struct gprs_llc_lle *lle;
1494 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1495
1496 /* DTAP - Attach Request */
1497 /* The P-TMSI is not known by the SGSN */
1498 static const unsigned char attach_req[] = {
1499 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1500 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1501 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1502 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1503 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1504 };
1505
1506 /* DTAP - Identity Response IMEI */
1507 static const unsigned char ident_resp_imei[] = {
1508 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1509 0x56
1510 };
1511
1512 /* DTAP - Identity Response IMSI */
1513 static const unsigned char ident_resp_imsi[] = {
1514 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1515 0x54
1516 };
1517
1518 /* DTAP - Attach Complete */
1519 static const unsigned char attach_compl[] = {
1520 0x08, 0x03
1521 };
1522
1523 printf("Testing cancellation\n");
1524
1525 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1526
1527 /* reset the PRNG used by sgsn_alloc_ptmsi */
1528 srand(1);
1529
1530 ptmsi1 = sgsn_alloc_ptmsi();
1531 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1532
1533 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1534 * again */
1535 srand(1);
1536
1537 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1538
1539 /* Create a LLE/LLME */
1540 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1541 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1542 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1543
1544 /* inject the attach request */
1545 send_0408_message(lle->llme, foreign_tlli,
1546 attach_req, ARRAY_SIZE(attach_req));
1547
1548 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1549 OSMO_ASSERT(ctx != NULL);
1550 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1551
1552 /* we expect an identity request (IMEI) */
1553 OSMO_ASSERT(sgsn_tx_counter == 1);
1554
1555 /* inject the identity response (IMEI) */
1556 send_0408_message(ctx->llme, foreign_tlli,
1557 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1558
1559 /* we expect an identity request (IMSI) */
1560 OSMO_ASSERT(sgsn_tx_counter == 1);
1561
1562 /* inject the identity response (IMSI) */
1563 send_0408_message(ctx->llme, foreign_tlli,
1564 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1565
1566 /* check that the MM context has not been removed due to a failed
1567 * authorization */
1568 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1569
1570 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1571
1572 /* we expect an attach accept/reject */
1573 OSMO_ASSERT(sgsn_tx_counter == 1);
1574
1575 /* this has been randomly assigned by the SGSN */
1576 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1577
1578 /* inject the attach complete */
1579 send_0408_message(ctx->llme, local_tlli,
1580 attach_compl, ARRAY_SIZE(attach_compl));
1581
1582 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1583
1584 /* we don't expect a response */
1585 OSMO_ASSERT(sgsn_tx_counter == 0);
1586
1587 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001588 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001589
1590 /* verify that things are gone */
1591 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1592 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1593 OSMO_ASSERT(!ictx);
1594
1595 sgsn->cfg.auth_policy = saved_auth_policy;
1596}
1597
1598/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001599 * Test the dynamic allocation of P-TMSIs
1600 */
1601static void test_gmm_ptmsi_allocation(void)
1602{
1603 struct gprs_ra_id raid = { 0, };
1604 struct sgsn_mm_ctx *ctx = NULL;
1605 struct sgsn_mm_ctx *ictx;
1606 uint32_t foreign_tlli;
1607 uint32_t ptmsi1;
1608 uint32_t ptmsi2;
1609 uint32_t old_ptmsi;
1610 uint32_t local_tlli = 0;
1611 struct gprs_llc_lle *lle;
1612 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1613
1614 /* DTAP - Attach Request (IMSI 12131415161718) */
1615 static const unsigned char attach_req[] = {
1616 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1617 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1618 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1619 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1620 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1621 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1622 0x00,
1623 };
1624
1625 /* DTAP - Identity Response IMEI */
1626 static const unsigned char ident_resp_imei[] = {
1627 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1628 0x56
1629 };
1630
1631 /* DTAP - Attach Complete */
1632 static const unsigned char attach_compl[] = {
1633 0x08, 0x03
1634 };
1635
1636 /* DTAP - Routing Area Update Request */
1637 static const unsigned char ra_upd_req[] = {
1638 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1639 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1640 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1641 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1642 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1643 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1644 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1645 };
1646
1647 /* DTAP - Routing Area Update Complete */
1648 static const unsigned char ra_upd_complete[] = {
1649 0x08, 0x0a
1650 };
1651
1652 /* DTAP - Detach Request (MO) */
1653 /* normal detach, power_off = 1 */
1654 static const unsigned char detach_req[] = {
1655 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1656 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1657 };
1658
1659 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1660
1661 printf("Testing P-TMSI allocation\n");
1662
1663 printf(" - sgsn_alloc_ptmsi\n");
1664
1665 /* reset the PRNG used by sgsn_alloc_ptmsi */
1666 srand(1);
1667
1668 ptmsi1 = sgsn_alloc_ptmsi();
1669 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1670
1671 ptmsi2 = sgsn_alloc_ptmsi();
1672 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1673
1674 OSMO_ASSERT(ptmsi1 != ptmsi2);
1675
1676 printf(" - Repeated Attach Request\n");
1677
1678 /* reset the PRNG, so that the same P-TMSI will be generated
1679 * again */
1680 srand(1);
1681
1682 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1683
1684 /* Create a LLE/LLME */
1685 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1686 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1687 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1688
1689 /* inject the attach request */
1690 send_0408_message(lle->llme, foreign_tlli,
1691 attach_req, ARRAY_SIZE(attach_req));
1692
1693 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1694 OSMO_ASSERT(ctx != NULL);
1695 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1696 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1697
1698 old_ptmsi = ctx->p_tmsi_old;
1699
1700 /* we expect an identity request (IMEI) */
1701 OSMO_ASSERT(sgsn_tx_counter == 1);
1702
1703 /* inject the identity response (IMEI) */
1704 send_0408_message(ctx->llme, foreign_tlli,
1705 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1706
1707 /* check that the MM context has not been removed due to a failed
1708 * authorization */
1709 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1710
1711 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1712 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1713
1714 /* we expect an attach accept */
1715 OSMO_ASSERT(sgsn_tx_counter == 1);
1716
1717 /* we ignore this and send the attach again */
1718 send_0408_message(lle->llme, foreign_tlli,
1719 attach_req, ARRAY_SIZE(attach_req));
1720
1721 /* the allocated P-TMSI should be the same */
1722 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1723 OSMO_ASSERT(ctx != NULL);
1724 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1725 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1726 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1727
1728 /* inject the attach complete */
1729 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1730 send_0408_message(ctx->llme, local_tlli,
1731 attach_compl, ARRAY_SIZE(attach_compl));
1732
1733 /* we don't expect a response */
1734 OSMO_ASSERT(sgsn_tx_counter == 0);
1735
1736 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1737 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1738 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1739
1740 printf(" - Repeated RA Update Request\n");
1741
1742 /* inject the RA update request */
1743 send_0408_message(ctx->llme, local_tlli,
1744 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1745
1746 /* we expect an RA update accept */
1747 OSMO_ASSERT(sgsn_tx_counter == 1);
1748
1749 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1750 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1751 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1752
1753 /* repeat the RA update request */
1754 send_0408_message(ctx->llme, local_tlli,
1755 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1756
1757 /* we expect an RA update accept */
1758 OSMO_ASSERT(sgsn_tx_counter == 1);
1759
1760 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1761 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1762 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1763
1764 /* inject the RA update complete */
1765 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1766 send_0408_message(ctx->llme, local_tlli,
1767 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1768
1769 /* we don't expect a response */
1770 OSMO_ASSERT(sgsn_tx_counter == 0);
1771
1772 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1773 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1774 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1775
1776 /* inject the detach */
1777 send_0408_message(ctx->llme, local_tlli,
1778 detach_req, ARRAY_SIZE(detach_req));
1779
1780 /* verify that things are gone */
1781 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1782 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1783 OSMO_ASSERT(!ictx);
1784
1785 sgsn->cfg.auth_policy = saved_auth_policy;
1786}
1787
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001788static void test_apn_matching(void)
1789{
1790 struct apn_ctx *actx, *actxs[9];
1791
1792 printf("Testing APN matching\n");
1793
1794 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1795 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1796 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1797 actxs[3] = NULL;
1798
1799 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1800 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1801 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1802 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1803
1804 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1805
1806 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1807 OSMO_ASSERT(actx == actxs[2]);
1808 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1809 OSMO_ASSERT(actx == actxs[2]);
1810 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1811 OSMO_ASSERT(actx == actxs[1]);
1812 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1813 OSMO_ASSERT(actx == actxs[1]);
1814 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1815 OSMO_ASSERT(actx == actxs[0]);
1816 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1817 OSMO_ASSERT(actx == NULL);
1818
1819 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1820 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1821 OSMO_ASSERT(actx == actxs[3]);
1822
1823 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1824 OSMO_ASSERT(actx == actxs[4]);
1825
1826 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1827 OSMO_ASSERT(actx == actxs[6]);
1828
1829 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1830 OSMO_ASSERT(actx == actxs[5]);
1831
1832 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1833 OSMO_ASSERT(actx == actxs[7]);
1834
1835 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1836 OSMO_ASSERT(actx == actxs[8]);
1837
1838 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1839 OSMO_ASSERT(actx == actxs[7]);
1840
1841 /* Free APN contexts and check how the matching changes */
1842
1843 sgsn_apn_ctx_free(actxs[7]);
1844 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1845 OSMO_ASSERT(actx == actxs[8]);
1846
1847 sgsn_apn_ctx_free(actxs[8]);
1848 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1849 OSMO_ASSERT(actx == actxs[6]);
1850
1851 sgsn_apn_ctx_free(actxs[6]);
1852 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1853 OSMO_ASSERT(actx == actxs[1]);
1854
1855 sgsn_apn_ctx_free(actxs[5]);
1856 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1857 OSMO_ASSERT(actx == actxs[4]);
1858
1859 sgsn_apn_ctx_free(actxs[4]);
1860 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1861 OSMO_ASSERT(actx == actxs[2]);
1862
1863 sgsn_apn_ctx_free(actxs[2]);
1864 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1865 OSMO_ASSERT(actx == actxs[1]);
1866
1867 sgsn_apn_ctx_free(actxs[1]);
1868 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1869 OSMO_ASSERT(actx == actxs[0]);
1870
1871 sgsn_apn_ctx_free(actxs[0]);
1872 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1873 OSMO_ASSERT(actx == actxs[3]);
1874
1875 sgsn_apn_ctx_free(actxs[3]);
1876 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1877 OSMO_ASSERT(actx == NULL);
1878}
1879
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001880struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1881 struct sgsn_subscriber_data *sdata);
1882
1883static void test_ggsn_selection(void)
1884{
1885 struct apn_ctx *actxs[4];
1886 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
1887 struct gsm_subscriber *s1;
1888 const char *imsi1 = "1234567890";
1889 struct sgsn_mm_ctx *ctx;
1890 struct gprs_ra_id raid = { 0, };
1891 uint32_t local_tlli = 0xffeeddcc;
1892 enum gsm48_gsm_cause gsm_cause;
1893 struct tlv_parsed tp;
1894 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1895 struct sgsn_subscriber_pdp_data *pdp_data;
1896
1897 printf("Testing GGSN selection\n");
1898
1899 gprs_gsup_client_send_cb = my_gprs_gsup_client_send_dummy;
1900
1901 /* Check for emptiness */
1902 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1903
1904 /* Create a context */
1905 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1906 ctx = alloc_mm_ctx(local_tlli, &raid);
1907 strncpy(ctx->imsi, imsi1, sizeof(ctx->imsi) - 1);
1908
1909 /* Allocate and attach a subscriber */
1910 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1911 assert_subscr(s1, imsi1);
1912
1913 tp.lv[GSM48_IE_GSM_APN].len = 0;
1914 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1915
1916 /* TODO: Add PDP info entries to s1 */
1917
1918 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1919 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1920 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1921
1922 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1923 actxs[0]->ggsn = ggcs[0];
1924 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1925 actxs[1]->ggsn = ggcs[1];
1926 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1927 actxs[2]->ggsn = ggcs[2];
1928
1929 /* Resolve GGSNs */
1930
1931 tp.lv[GSM48_IE_GSM_APN].len =
1932 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1933
1934 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1935 OSMO_ASSERT(ggc != NULL);
1936 OSMO_ASSERT(ggc->id == 0);
1937
1938 tp.lv[GSM48_IE_GSM_APN].len =
1939 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1940
1941 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1942 OSMO_ASSERT(ggc != NULL);
1943 OSMO_ASSERT(ggc->id == 1);
1944
1945 tp.lv[GSM48_IE_GSM_APN].len = 0;
1946 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1947
1948 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1949 OSMO_ASSERT(ggc != NULL);
1950 OSMO_ASSERT(ggc->id == 0);
1951
1952 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1953 actxs[3]->ggsn = ggcs[2];
1954 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1955 OSMO_ASSERT(ggc != NULL);
1956 OSMO_ASSERT(ggc->id == 2);
1957
1958 sgsn_apn_ctx_free(actxs[3]);
1959 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1960
1961 tp.lv[GSM48_IE_GSM_APN].len =
1962 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1963
1964 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1965 OSMO_ASSERT(ggc == NULL);
1966 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
1967
1968 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
1969 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1970 OSMO_ASSERT(ggc == NULL);
1971 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1972
1973 /* Add PDP data entry to subscriber */
1974
1975 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1976 pdp_data->context_id = 1;
1977
1978 pdp_data->pdp_type = 0x0121;
1979 strncpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str)-1);
1980
1981 tp.lv[GSM48_IE_GSM_APN].len =
1982 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1983
1984 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1985 OSMO_ASSERT(ggc != NULL);
1986 OSMO_ASSERT(ggc->id == 0);
1987
1988 tp.lv[GSM48_IE_GSM_APN].len =
1989 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1990
1991 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1992 OSMO_ASSERT(ggc == NULL);
1993 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
1994
1995 /* Cleanup */
1996
1997 subscr_put(s1);
1998 sgsn_mm_ctx_cleanup_free(ctx);
1999
2000 assert_no_subscrs();
2001
2002 sgsn_apn_ctx_free(actxs[0]);
2003 sgsn_apn_ctx_free(actxs[1]);
2004 sgsn_apn_ctx_free(actxs[2]);
2005
2006 sgsn_ggsn_ctx_free(ggcs[0]);
2007 sgsn_ggsn_ctx_free(ggcs[1]);
2008 sgsn_ggsn_ctx_free(ggcs[2]);
2009
2010 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
2011}
2012
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002013static struct log_info_cat gprs_categories[] = {
2014 [DMM] = {
2015 .name = "DMM",
2016 .description = "Layer3 Mobility Management (MM)",
2017 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01002018 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002019 },
2020 [DPAG] = {
2021 .name = "DPAG",
2022 .description = "Paging Subsystem",
2023 .color = "\033[1;38m",
2024 .enabled = 1, .loglevel = LOGL_NOTICE,
2025 },
2026 [DMEAS] = {
2027 .name = "DMEAS",
2028 .description = "Radio Measurement Processing",
2029 .enabled = 0, .loglevel = LOGL_NOTICE,
2030 },
2031 [DREF] = {
2032 .name = "DREF",
2033 .description = "Reference Counting",
2034 .enabled = 0, .loglevel = LOGL_NOTICE,
2035 },
2036 [DGPRS] = {
2037 .name = "DGPRS",
2038 .description = "GPRS Packet Service",
2039 .enabled = 1, .loglevel = LOGL_DEBUG,
2040 },
2041 [DNS] = {
2042 .name = "DNS",
2043 .description = "GPRS Network Service (NS)",
2044 .enabled = 1, .loglevel = LOGL_INFO,
2045 },
2046 [DBSSGP] = {
2047 .name = "DBSSGP",
2048 .description = "GPRS BSS Gateway Protocol (BSSGP)",
2049 .enabled = 1, .loglevel = LOGL_DEBUG,
2050 },
2051 [DLLC] = {
2052 .name = "DLLC",
2053 .description = "GPRS Logical Link Control Protocol (LLC)",
2054 .enabled = 1, .loglevel = LOGL_DEBUG,
2055 },
2056 [DSNDCP] = {
2057 .name = "DSNDCP",
2058 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
2059 .enabled = 1, .loglevel = LOGL_DEBUG,
2060 },
2061};
2062
2063static struct log_info info = {
2064 .cat = gprs_categories,
2065 .num_cat = ARRAY_SIZE(gprs_categories),
2066};
2067
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002068int main(int argc, char **argv)
2069{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002070 void *osmo_sgsn_ctx;
2071
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002072 osmo_init_logging(&info);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002073 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
2074 tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
2075 tall_msgb_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "msgb");
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002076
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01002077 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002078 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01002079
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002080 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002081 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01002082 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01002083 test_subscriber_gsup();
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +01002084 test_subscriber_blocking();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02002085 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01002086 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02002087 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01002088 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01002089 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01002090 test_gmm_attach_acl();
2091 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01002092 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01002093 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01002094 test_gmm_attach_subscr_gsup_auth(0);
2095 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01002096 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01002097 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01002098 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01002099 test_gmm_ptmsi_allocation();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01002100 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01002101 test_ggsn_selection();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002102 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01002103
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002104 talloc_report_full(osmo_sgsn_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01002105 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002106 OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002107 return 0;
2108}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002109
2110
2111/* stubs */
2112struct osmo_prim_hdr;
2113int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
2114{
2115 abort();
2116}