blob: 64570038ec778dca9112bb11c5ac7125e5971c38 [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
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400417#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
418
419 static const uint8_t s1_msisdn[] = { MSISDN };
420
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100421 static const uint8_t update_location_res[] = {
422 0x06,
423 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400424 0x08, 0x09, MSISDN,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100425 0x04, 0x00, /* PDP info complete */
426 0x05, 0x12,
427 0x10, 0x01, 0x01,
428 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
429 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
430 0x05, 0x11,
431 0x10, 0x01, 0x02,
432 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
433 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
434 };
435
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400436#undef MSISDN
437
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100438 static const uint8_t update_location_err[] = {
439 0x05,
440 TEST_GSUP_IMSI1_IE,
441 0x02, 0x01, 0x07 /* GPRS not allowed */
442 };
443
444 static const uint8_t location_cancellation_req[] = {
445 0x1c,
446 TEST_GSUP_IMSI1_IE,
447 0x06, 0x01, 0x00,
448 };
449
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200450 static const uint8_t location_cancellation_req_withdraw[] = {
451 0x1c,
452 TEST_GSUP_IMSI1_IE,
453 0x06, 0x01, 0x01,
454 };
455
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100456 static const uint8_t location_cancellation_req_other[] = {
457 0x1c,
458 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
459 0x06, 0x01, 0x00,
460 };
461
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100462 static const uint8_t purge_ms_err[] = {
463 0x0d,
464 TEST_GSUP_IMSI1_IE,
465 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
466 };
467
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100468 static const uint8_t purge_ms_err_no_cause[] = {
469 0x0d,
470 TEST_GSUP_IMSI1_IE,
471 };
472
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100473 static const uint8_t purge_ms_res[] = {
474 0x0e,
475 TEST_GSUP_IMSI1_IE,
476 0x07, 0x00,
477 };
478
479
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100480 static const uint8_t insert_data_req[] = {
481 0x10,
482 TEST_GSUP_IMSI1_IE,
483 0x05, 0x11,
484 0x10, 0x01, 0x03,
485 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
486 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
487 };
488
489 static const uint8_t delete_data_req[] = {
490 0x14,
491 TEST_GSUP_IMSI1_IE,
492 0x10, 0x01, 0x03,
493 };
494
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100495 printf("Testing subcriber GSUP handling\n");
496
497 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
498
499 /* Check for emptiness */
500 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
501
502 /* Allocate entry 1 */
503 s1 = gprs_subscr_get_or_create(imsi1);
504 s1->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
505 s1found = gprs_subscr_get_by_imsi(imsi1);
506 OSMO_ASSERT(s1found == s1);
507 subscr_put(s1found);
508
509 /* Create a context */
510 OSMO_ASSERT(count(gprs_llme_list()) == 0);
511 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100512
513 /* Attach s1 to ctx */
514 ctx->subscr = subscr_get(s1);
515 ctx->subscr->sgsn_data->mm = ctx;
516
517 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100518 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100519 OSMO_ASSERT(rc >= 0);
520 OSMO_ASSERT(last_updated_subscr == s1);
521
522 /* Check triplets */
523 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
524 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
525 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
526
527 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100528 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100529 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100530 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100531 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100532
533 /* Check triplets */
534 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
535 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
536 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
537
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100538 /* Inject UpdateLocRes GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100539 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100540 OSMO_ASSERT(rc >= 0);
541 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100542 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100543 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400544 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
545 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100546 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
547 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
548 struct sgsn_subscriber_pdp_data, list);
549 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
550 pdpd = llist_entry(pdpd->list.next,
551 struct sgsn_subscriber_pdp_data, list);
552 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100553
554 /* Check authorization */
555 OSMO_ASSERT(s1->authorized == 1);
556
557 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100558 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100559 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100560 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100561 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100562
563 /* Check authorization */
564 OSMO_ASSERT(s1->authorized == 0);
565
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100566 /* Inject InsertSubscrData GSUP message */
567 last_updated_subscr = NULL;
568 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
569 OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
570 OSMO_ASSERT(last_updated_subscr == NULL);
571
572 /* Inject DeleteSubscrData GSUP message */
573 last_updated_subscr = NULL;
574 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
575 OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
576 OSMO_ASSERT(last_updated_subscr == NULL);
577
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100578 /* Inject wrong LocCancelReq GSUP message */
579 last_updated_subscr = NULL;
580 rc = rx_gsup_message(location_cancellation_req_other,
581 sizeof(location_cancellation_req_other));
582 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
583 OSMO_ASSERT(last_updated_subscr == NULL);
584
585 /* Check cancellation result */
586 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
587 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
588
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100589 /* Inject LocCancelReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100590 rc = rx_gsup_message(location_cancellation_req,
591 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100592 OSMO_ASSERT(rc >= 0);
593 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100594 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100595
596 /* Check cancellation result */
597 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
598 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
599
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200600 /* Inject LocCancelReq(withdraw) GSUP message */
601 rc = rx_gsup_message(location_cancellation_req_withdraw,
602 sizeof(location_cancellation_req_withdraw));
603 OSMO_ASSERT(rc >= 0);
604 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
605
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100606 /* Inject PurgeMsRes GSUP message */
607 rc = rx_gsup_message(purge_ms_res,
608 sizeof(purge_ms_res));
609 OSMO_ASSERT(rc >= 0);
610 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
611
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100612 /* Free MM context and subscriber */
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +0100613 OSMO_ASSERT(ctx->subscr == NULL);
614 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100615 subscr_put(s1);
616 s1found = gprs_subscr_get_by_imsi(imsi1);
617 OSMO_ASSERT(s1found == NULL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100618
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100619 /* Inject PurgeMsRes GSUP message */
620 rc = rx_gsup_message(purge_ms_res,
621 sizeof(purge_ms_res));
622 OSMO_ASSERT(rc >= 0);
623
624 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
625 rc = rx_gsup_message(purge_ms_err,
626 sizeof(purge_ms_err));
627 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
628
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100629 /* Inject PurgeMsErr() GSUP message */
630 rc = rx_gsup_message(purge_ms_err_no_cause,
631 sizeof(purge_ms_err_no_cause));
632 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
633
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100634 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
635 last_updated_subscr = NULL;
636 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100637 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100638 OSMO_ASSERT(last_updated_subscr == NULL);
639
640 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
641 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
642 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
643 OSMO_ASSERT(last_updated_subscr == NULL);
644
645 /* Inject LocCancelReq GSUP message (unknown IMSI) */
646 rc = rx_gsup_message(location_cancellation_req,
647 sizeof(location_cancellation_req));
648 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
649 OSMO_ASSERT(last_updated_subscr == NULL);
650
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100651 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
652}
653
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100654int my_gprs_gsup_client_send_dummy(struct gprs_gsup_client *gsupc, struct msgb *msg)
655{
656 msgb_free(msg);
657 return 0;
658};
659
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200660/*
661 * Test that a GMM Detach will remove the MMCTX and the
662 * associated LLME.
663 */
664static void test_gmm_detach(void)
665{
666 struct gprs_ra_id raid = { 0, };
667 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200668 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200669
670 printf("Testing GMM detach\n");
671
672 /* DTAP - Detach Request (MO) */
673 /* normal detach, power_off = 0 */
674 static const unsigned char detach_req[] = {
675 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
676 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
677 };
678
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200679 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200680
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100681 /* Create a context */
682 OSMO_ASSERT(count(gprs_llme_list()) == 0);
683 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200684
685 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100686 send_0408_message(ctx->llme, local_tlli,
687 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200688
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100689 /* verify that a single message (hopefully the Detach Accept) has been
690 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100691 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100692
693 /* verify that things are gone */
694 OSMO_ASSERT(count(gprs_llme_list()) == 0);
695 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
696 OSMO_ASSERT(!ictx);
697}
698
699/*
700 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
701 * will not sent a Detach Accept message (power_off = 1)
702 */
703static void test_gmm_detach_power_off(void)
704{
705 struct gprs_ra_id raid = { 0, };
706 struct sgsn_mm_ctx *ctx, *ictx;
707 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100708
709 printf("Testing GMM detach (power off)\n");
710
711 /* DTAP - Detach Request (MO) */
712 /* normal detach, power_off = 1 */
713 static const unsigned char detach_req[] = {
714 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
715 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
716 };
717
718 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
719
720 /* Create a context */
721 OSMO_ASSERT(count(gprs_llme_list()) == 0);
722 ctx = alloc_mm_ctx(local_tlli, &raid);
723
724 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100725 send_0408_message(ctx->llme, local_tlli,
726 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100727
728 /* verify that no message (and therefore no Detach Accept) has been
729 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100730 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100731
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200732 /* verify that things are gone */
733 OSMO_ASSERT(count(gprs_llme_list()) == 0);
734 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200735 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200736}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200737
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200738/*
739 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
740 */
741static void test_gmm_detach_no_mmctx(void)
742{
743 struct gprs_llc_lle *lle;
744 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200745
746 printf("Testing GMM detach (no MMCTX)\n");
747
748 /* DTAP - Detach Request (MO) */
749 /* normal detach, power_off = 0 */
750 static const unsigned char detach_req[] = {
751 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
752 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
753 };
754
755 /* Create an LLME */
756 OSMO_ASSERT(count(gprs_llme_list()) == 0);
757 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
758 lle = gprs_lle_get_or_create(local_tlli, 3);
759
760 OSMO_ASSERT(count(gprs_llme_list()) == 1);
761
762 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100763 send_0408_message(lle->llme, local_tlli,
764 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200765
766 /* verify that the LLME is gone */
767 OSMO_ASSERT(count(gprs_llme_list()) == 0);
768}
769
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100770/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100771 * Test that a single GMM Detach Accept message will not cause the SGSN to send
772 * any message or leave an MM context at the SGSN.
773 */
774static void test_gmm_detach_accept_unexpected(void)
775{
776 struct gprs_llc_lle *lle;
777 uint32_t local_tlli;
778
779 printf("Testing GMM detach accept (unexpected)\n");
780
781 /* DTAP - Detach Accept (MT) */
782 /* normal detach */
783 static const unsigned char detach_acc[] = {
784 0x08, 0x06
785 };
786
787 /* Create an LLME */
788 OSMO_ASSERT(count(gprs_llme_list()) == 0);
789 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
790 lle = gprs_lle_get_or_create(local_tlli, 3);
791
792 /* inject the detach */
793 send_0408_message(lle->llme, local_tlli,
794 detach_acc, ARRAY_SIZE(detach_acc));
795
796 /* verify that no message (and therefore no Status or XID reset) has been
797 * sent by the SGSN */
798 OSMO_ASSERT(sgsn_tx_counter == 0);
799
800 /* verify that things are gone */
801 OSMO_ASSERT(count(gprs_llme_list()) == 0);
802}
803
804/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100805 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
806 */
807static void test_gmm_status_no_mmctx(void)
808{
809 struct gprs_llc_lle *lle;
810 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100811
812 printf("Testing GMM Status (no MMCTX)\n");
813
814 /* DTAP - GMM Status, protocol error */
815 static const unsigned char gmm_status[] = {
816 0x08, 0x20, 0x6f
817 };
818
819 /* Create an LLME */
820 OSMO_ASSERT(count(gprs_llme_list()) == 0);
821 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
822 lle = gprs_lle_get_or_create(local_tlli, 3);
823
824 OSMO_ASSERT(count(gprs_llme_list()) == 1);
825
826 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100827 send_0408_message(lle->llme, local_tlli,
828 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100829
830 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100831 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100832
833 /* verify that the LLME is gone */
834 OSMO_ASSERT(count(gprs_llme_list()) == 0);
835}
836
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100837/*
838 * Test the GMM Attach procedure
839 */
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100840static void test_gmm_attach(int retry)
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100841{
842 struct gprs_ra_id raid = { 0, };
843 struct sgsn_mm_ctx *ctx = NULL;
844 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100845 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100846 uint32_t foreign_tlli;
847 uint32_t local_tlli = 0;
848 struct gprs_llc_lle *lle;
849
850 /* DTAP - Attach Request */
851 /* The P-TMSI is not known by the SGSN */
852 static const unsigned char attach_req[] = {
853 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
854 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
855 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
856 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
857 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
858 };
859
860 /* DTAP - Identity Response IMEI */
861 static const unsigned char ident_resp_imei[] = {
862 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
863 0x56
864 };
865
866 /* DTAP - Identity Response IMSI */
867 static const unsigned char ident_resp_imsi[] = {
868 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
869 0x54
870 };
871
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100872 /* DTAP - Authentication and Ciphering Resp */
873 static const unsigned char auth_ciph_resp[] = {
874 0x08, 0x13, 0x00, 0x22, 0x51, 0xe5, 0x51, 0xe5, 0x23, 0x09,
875 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x01
876 };
877
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100878 /* DTAP - Attach Complete */
879 static const unsigned char attach_compl[] = {
880 0x08, 0x03
881 };
882
883 /* DTAP - Detach Request (MO) */
884 /* normal detach, power_off = 0 */
885 static const unsigned char detach_req[] = {
886 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
887 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
888 };
889
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100890 printf("Testing GMM attach%s\n", retry ? " with retry" : "");
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100891
892 /* reset the PRNG used by sgsn_alloc_ptmsi */
893 srand(1);
894
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100895 ptmsi1 = sgsn_alloc_ptmsi();
896 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
897
898 /* reset the PRNG, so that the same P-TMSI sequence will be generated
899 * again */
900 srand(1);
901
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100902 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
903
904 /* Create a LLE/LLME */
905 OSMO_ASSERT(count(gprs_llme_list()) == 0);
906 lle = gprs_lle_get_or_create(foreign_tlli, 3);
907 OSMO_ASSERT(count(gprs_llme_list()) == 1);
908
909 /* inject the attach request */
910 send_0408_message(lle->llme, foreign_tlli,
911 attach_req, ARRAY_SIZE(attach_req));
912
913 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
914 OSMO_ASSERT(ctx != NULL);
915 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
916
917 /* we expect an identity request (IMEI) */
918 OSMO_ASSERT(sgsn_tx_counter == 1);
919
920 /* inject the identity response (IMEI) */
921 send_0408_message(ctx->llme, foreign_tlli,
922 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
923
924 /* we expect an identity request (IMSI) */
925 OSMO_ASSERT(sgsn_tx_counter == 1);
926
927 /* inject the identity response (IMSI) */
928 send_0408_message(ctx->llme, foreign_tlli,
929 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
930
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100931 /* check that the MM context has not been removed due to a failed
932 * authorization */
933 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
934
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100935 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100936
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100937retry_attach_req:
938
939 if (retry && sgsn_tx_counter == 0) {
940 fprintf(stderr, "Retrying attach request\n");
941 /* re-inject the attach request */
942 send_0408_message(lle->llme, foreign_tlli,
943 attach_req, ARRAY_SIZE(attach_req));
944 }
945
946 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && sgsn_tx_counter == 1) {
947 /* we got an auth & ciph request */
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100948
949 /* inject the auth & ciph response */
950 send_0408_message(ctx->llme, foreign_tlli,
951 auth_ciph_resp, ARRAY_SIZE(auth_ciph_resp));
952
953 /* check that the MM context has not been removed due to a
954 * failed authorization */
955 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
Holger Hans Peter Freyther20de3ae2015-05-05 22:52:40 +0200956 if (ctx->subscr && ctx->subscr->sgsn_data->msisdn_len > 0)
957 OSMO_ASSERT(strcmp(ctx->msisdn, "+49166213323") == 0);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100958 }
959
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100960 if (retry && sgsn_tx_counter == 0)
961 goto retry_attach_req;
962
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100963 /* we expect an attach accept/reject */
964 OSMO_ASSERT(sgsn_tx_counter == 1);
965
966 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100967 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100968
969 /* inject the attach complete */
970 send_0408_message(ctx->llme, local_tlli,
971 attach_compl, ARRAY_SIZE(attach_compl));
972
973 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
974
975 /* we don't expect a response */
976 OSMO_ASSERT(sgsn_tx_counter == 0);
977
978 /* inject the detach */
979 send_0408_message(ctx->llme, local_tlli,
980 detach_req, ARRAY_SIZE(detach_req));
981
982 /* verify that things are gone */
983 OSMO_ASSERT(count(gprs_llme_list()) == 0);
984 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
985 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100986}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100987
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100988static void test_gmm_attach_acl(void)
989{
990 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
991
992 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
993 sgsn_acl_add("123456789012345", &sgsn->cfg);
994 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100995 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100996 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100997
998 sgsn->cfg.auth_policy = saved_auth_policy;
999}
1000
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001001int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001002 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001003 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001004 if (rc == -ENOTSUP) {
1005 OSMO_ASSERT(mmctx->subscr);
1006 gprs_subscr_update(mmctx->subscr);
1007 }
1008 return rc;
1009};
1010
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001011int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
1012 gprs_subscr_update(mmctx->subscr);
1013 return 0;
1014};
1015
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001016static void test_gmm_attach_subscr(void)
1017{
1018 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1019 struct gsm_subscriber *subscr;
1020
1021 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001022 subscr_request_update_location_cb = my_subscr_request_update_location;
1023 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001024
1025 subscr = gprs_subscr_get_or_create("123456789012345");
1026 subscr->authorized = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001027
1028 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001029 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001030 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001031 assert_no_subscrs();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001032
1033 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001034 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1035 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001036}
1037
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001038int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
1039{
1040 /* Fake an authentication */
1041 OSMO_ASSERT(mmctx->subscr);
1042 mmctx->is_authenticated = 1;
1043 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001044
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001045 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001046};
1047
1048static void test_gmm_attach_subscr_fake_auth(void)
1049{
1050 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1051 struct gsm_subscriber *subscr;
1052
1053 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001054 subscr_request_update_location_cb = my_subscr_request_update_location;
1055 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001056
1057 subscr = gprs_subscr_get_or_create("123456789012345");
1058 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001059 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001060 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001061
1062 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001063 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001064 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001065 assert_no_subscrs();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001066
1067 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001068 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1069 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
1070}
1071
1072int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
1073{
1074 struct gsm_auth_tuple at = {
1075 .sres = {0x51, 0xe5, 0x51, 0xe5},
1076 .key_seq = 0
1077 };
1078
1079 /* Fake an authentication */
1080 OSMO_ASSERT(mmctx->subscr);
1081 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
1082
1083 gprs_subscr_update_auth_info(mmctx->subscr);
1084
1085 return 0;
1086};
1087
1088static void test_gmm_attach_subscr_real_auth(void)
1089{
1090 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1091 struct gsm_subscriber *subscr;
1092
1093 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1094 subscr_request_update_location_cb = my_subscr_request_update_location;
1095 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
1096
1097 subscr = gprs_subscr_get_or_create("123456789012345");
1098 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001099 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001100 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001101
1102 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001103
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001104 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001105 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001106 assert_no_subscrs();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001107
1108 sgsn->cfg.auth_policy = saved_auth_policy;
1109 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1110 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001111}
1112
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001113#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
1114 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
1115
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001116static int auth_info_skip = 0;
1117static int upd_loc_skip = 0;
1118
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001119int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
1120{
1121 static const uint8_t send_auth_info_res[] = {
1122 0x0a,
1123 TEST_GSUP_IMSI_LONG_IE,
1124 0x03, 0x22, /* Auth tuple */
1125 0x20, 0x10,
1126 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1127 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1128 0x21, 0x04,
1129 0x51, 0xe5, 0x51, 0xe5,
1130 0x22, 0x08,
1131 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1132 };
1133
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001134 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001135
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001136 if (auth_info_skip > 0) {
1137 auth_info_skip -= 1;
1138 return -EAGAIN;
1139 }
1140
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001141 /* Fake an SendAuthInfoRes */
1142 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1143
1144 return 0;
1145};
1146
1147int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1148 static const uint8_t update_location_res[] = {
1149 0x06,
1150 TEST_GSUP_IMSI_LONG_IE,
1151 0x04, 0x00, /* PDP info complete */
1152 0x05, 0x12,
1153 0x10, 0x01, 0x01,
1154 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1155 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freyther20de3ae2015-05-05 22:52:40 +02001156 0x08, 0x07, /* MSISDN 49166213323 encoded */
1157 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freyther10c0f562015-05-17 20:58:40 +02001158 0x09, 0x07, /* MSISDN 38166213323 encoded */
1159 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001160 };
1161
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001162 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001163
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001164 if (upd_loc_skip > 0) {
1165 upd_loc_skip -= 1;
1166 return -EAGAIN;
1167 }
1168
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001169 /* Fake an UpdateLocRes */
1170 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1171};
1172
1173
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001174static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001175{
1176 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1177 struct gsm_subscriber *subscr;
1178
1179 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1180 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1181 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001182 if (retry) {
1183 upd_loc_skip = 3;
1184 auth_info_skip = 3;
1185 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001186
1187 subscr = gprs_subscr_get_or_create("123456789012345");
1188 subscr->authorized = 1;
1189 sgsn->cfg.require_authentication = 1;
1190 sgsn->cfg.require_update_location = 1;
1191 subscr_put(subscr);
1192
1193 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001194 test_gmm_attach(retry);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001195 assert_no_subscrs();
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001196
1197 sgsn->cfg.auth_policy = saved_auth_policy;
1198 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1199 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001200 upd_loc_skip = 0;
1201 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001202}
1203
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001204int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1205{
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001206 struct gprs_gsup_message to_peer = {0};
1207 struct gprs_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001208 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001209 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001210
1211 /* Simulate the GSUP peer */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001212 rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1213 OSMO_ASSERT(rc >= 0);
1214 OSMO_ASSERT(to_peer.imsi[0] != 0);
1215 strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001216
1217 /* This invalidates the pointers in to_peer */
1218 msgb_free(msg);
1219
1220 switch (to_peer.message_type) {
1221 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1222 /* Send UPDATE_LOCATION_RESULT */
1223 return my_subscr_request_update_gsup_auth(NULL);
1224
1225 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1226 /* Send SEND_AUTH_INFO_RESULT */
1227 return my_subscr_request_auth_info_gsup_auth(NULL);
1228
1229 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001230 from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
1231 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001232
1233 default:
1234 if ((to_peer.message_type & 0b00000011) == 0) {
1235 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001236 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001237 from_peer.message_type = to_peer.message_type + 1;
1238 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1239 break;
1240 }
1241
1242 /* Ignore it */
1243 return 0;
1244 }
1245
1246 reply_msg = gprs_gsup_msgb_alloc();
1247 reply_msg->l2h = reply_msg->data;
1248 gprs_gsup_encode(reply_msg, &from_peer);
1249 gprs_subscr_rx_gsup_message(reply_msg);
1250 msgb_free(reply_msg);
1251
1252 return 0;
1253};
1254
1255static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1256{
1257 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1258 struct gsm_subscriber *subscr;
1259
1260 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001261 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1262
1263 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1264
1265 if (retry) {
1266 upd_loc_skip = 3;
1267 auth_info_skip = 3;
1268 }
1269
1270 printf("Auth policy 'remote', real GSUP based auth: ");
1271 test_gmm_attach(retry);
1272
1273 subscr = gprs_subscr_get_by_imsi("123456789012345");
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001274 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001275 assert_no_subscrs();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001276
1277 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001278 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1279 upd_loc_skip = 0;
1280 auth_info_skip = 0;
1281 talloc_free(sgsn->gsup_client);
1282 sgsn->gsup_client = NULL;
1283}
1284
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001285/*
1286 * Test the GMM Rejects
1287 */
1288static void test_gmm_reject(void)
1289{
1290 struct gprs_ra_id raid = { 0, };
1291 struct sgsn_mm_ctx *ctx = NULL;
1292 uint32_t foreign_tlli;
1293 struct gprs_llc_lle *lle;
1294 int idx;
1295
1296 /* DTAP - Attach Request */
1297 /* Invalid MI length */
1298 static const unsigned char attach_req_inv_mi_len[] = {
1299 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1300 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1301 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1302 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1303 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1304 };
1305
1306 /* DTAP - Attach Request */
1307 /* Invalid MI type (IMEI) */
1308 static const unsigned char attach_req_inv_mi_type[] = {
1309 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1310 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1311 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1312 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1313 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1314 };
1315
1316 /* DTAP - Routing Area Update Request */
1317 static const unsigned char dtap_ra_upd_req[] = {
1318 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1319 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1320 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1321 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1322 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1323 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1324 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1325 };
1326
1327 /* DTAP - Routing Area Update Request */
1328 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1329 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1330 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1331 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1332 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1333 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1334 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1335 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1336 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1337 };
1338
1339 /* DTAP - Routing Area Update Request */
1340 /* Invalid cap length */
1341 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1342 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1343 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1344 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1345 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1346 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1347 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1348 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1349 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1350 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1351 };
1352
1353 struct test {
1354 const char *title;
1355 const unsigned char *msg;
1356 unsigned msg_len;
1357 unsigned num_resp;
1358
1359 };
1360 static struct test tests[] = {
1361 {
1362 .title = "Attach Request (invalid MI length)",
1363 .msg = attach_req_inv_mi_len,
1364 .msg_len = sizeof(attach_req_inv_mi_len),
1365 .num_resp = 1 /* Reject */
1366
1367 },
1368 {
1369 .title = "Attach Request (invalid MI type)",
1370 .msg = attach_req_inv_mi_type,
1371 .msg_len = sizeof(attach_req_inv_mi_type),
1372 .num_resp = 1 /* Reject */
1373 },
1374 {
1375 .title = "Routing Area Update Request (valid)",
1376 .msg = dtap_ra_upd_req,
1377 .msg_len = sizeof(dtap_ra_upd_req),
1378 .num_resp = 2 /* XID Reset + Reject */
1379 },
1380 {
1381 .title = "Routing Area Update Request (invalid type)",
1382 .msg = dtap_ra_upd_req_inv_type,
1383 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1384 .num_resp = 1 /* Reject */
1385 },
1386 {
1387 .title = "Routing Area Update Request (invalid CAP length)",
1388 .msg = dtap_ra_upd_req_inv_cap_len,
1389 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1390 .num_resp = 1 /* Reject */
1391 },
1392 };
1393
1394 printf("Testing GMM reject\n");
1395
1396 /* reset the PRNG used by sgsn_alloc_ptmsi */
1397 srand(1);
1398
1399 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1400
1401 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1402
1403 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1404 const struct test *test = &tests[idx];
1405 printf(" - %s\n", test->title);
1406
1407 /* Create a LLE/LLME */
1408 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1409 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1410
1411 /* Inject the Request message */
1412 send_0408_message(lle->llme, foreign_tlli,
1413 test->msg, test->msg_len);
1414
1415 /* We expect a Reject message */
1416 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1417 sgsn_tx_counter, test->num_resp);
1418 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1419
1420 /* verify that LLME/MM are removed */
1421 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1422 OSMO_ASSERT(ctx == NULL);
1423 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1424 }
1425}
1426
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001427/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001428 * Test cancellation of attached MM contexts
1429 */
1430static void test_gmm_cancel(void)
1431{
1432 struct gprs_ra_id raid = { 0, };
1433 struct sgsn_mm_ctx *ctx = NULL;
1434 struct sgsn_mm_ctx *ictx;
1435 uint32_t ptmsi1;
1436 uint32_t foreign_tlli;
1437 uint32_t local_tlli = 0;
1438 struct gprs_llc_lle *lle;
1439 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1440
1441 /* DTAP - Attach Request */
1442 /* The P-TMSI is not known by the SGSN */
1443 static const unsigned char attach_req[] = {
1444 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1445 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1446 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1447 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1448 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1449 };
1450
1451 /* DTAP - Identity Response IMEI */
1452 static const unsigned char ident_resp_imei[] = {
1453 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1454 0x56
1455 };
1456
1457 /* DTAP - Identity Response IMSI */
1458 static const unsigned char ident_resp_imsi[] = {
1459 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1460 0x54
1461 };
1462
1463 /* DTAP - Attach Complete */
1464 static const unsigned char attach_compl[] = {
1465 0x08, 0x03
1466 };
1467
1468 printf("Testing cancellation\n");
1469
1470 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1471
1472 /* reset the PRNG used by sgsn_alloc_ptmsi */
1473 srand(1);
1474
1475 ptmsi1 = sgsn_alloc_ptmsi();
1476 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1477
1478 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1479 * again */
1480 srand(1);
1481
1482 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1483
1484 /* Create a LLE/LLME */
1485 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1486 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1487 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1488
1489 /* inject the attach request */
1490 send_0408_message(lle->llme, foreign_tlli,
1491 attach_req, ARRAY_SIZE(attach_req));
1492
1493 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1494 OSMO_ASSERT(ctx != NULL);
1495 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1496
1497 /* we expect an identity request (IMEI) */
1498 OSMO_ASSERT(sgsn_tx_counter == 1);
1499
1500 /* inject the identity response (IMEI) */
1501 send_0408_message(ctx->llme, foreign_tlli,
1502 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1503
1504 /* we expect an identity request (IMSI) */
1505 OSMO_ASSERT(sgsn_tx_counter == 1);
1506
1507 /* inject the identity response (IMSI) */
1508 send_0408_message(ctx->llme, foreign_tlli,
1509 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1510
1511 /* check that the MM context has not been removed due to a failed
1512 * authorization */
1513 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1514
1515 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1516
1517 /* we expect an attach accept/reject */
1518 OSMO_ASSERT(sgsn_tx_counter == 1);
1519
1520 /* this has been randomly assigned by the SGSN */
1521 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1522
1523 /* inject the attach complete */
1524 send_0408_message(ctx->llme, local_tlli,
1525 attach_compl, ARRAY_SIZE(attach_compl));
1526
1527 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1528
1529 /* we don't expect a response */
1530 OSMO_ASSERT(sgsn_tx_counter == 0);
1531
1532 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001533 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001534
1535 /* verify that things are gone */
1536 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1537 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1538 OSMO_ASSERT(!ictx);
1539
1540 sgsn->cfg.auth_policy = saved_auth_policy;
1541}
1542
1543/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001544 * Test the dynamic allocation of P-TMSIs
1545 */
1546static void test_gmm_ptmsi_allocation(void)
1547{
1548 struct gprs_ra_id raid = { 0, };
1549 struct sgsn_mm_ctx *ctx = NULL;
1550 struct sgsn_mm_ctx *ictx;
1551 uint32_t foreign_tlli;
1552 uint32_t ptmsi1;
1553 uint32_t ptmsi2;
1554 uint32_t old_ptmsi;
1555 uint32_t local_tlli = 0;
1556 struct gprs_llc_lle *lle;
1557 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1558
1559 /* DTAP - Attach Request (IMSI 12131415161718) */
1560 static const unsigned char attach_req[] = {
1561 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1562 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1563 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1564 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1565 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1566 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1567 0x00,
1568 };
1569
1570 /* DTAP - Identity Response IMEI */
1571 static const unsigned char ident_resp_imei[] = {
1572 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1573 0x56
1574 };
1575
1576 /* DTAP - Attach Complete */
1577 static const unsigned char attach_compl[] = {
1578 0x08, 0x03
1579 };
1580
1581 /* DTAP - Routing Area Update Request */
1582 static const unsigned char ra_upd_req[] = {
1583 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1584 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1585 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1586 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1587 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1588 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1589 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1590 };
1591
1592 /* DTAP - Routing Area Update Complete */
1593 static const unsigned char ra_upd_complete[] = {
1594 0x08, 0x0a
1595 };
1596
1597 /* DTAP - Detach Request (MO) */
1598 /* normal detach, power_off = 1 */
1599 static const unsigned char detach_req[] = {
1600 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1601 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1602 };
1603
1604 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1605
1606 printf("Testing P-TMSI allocation\n");
1607
1608 printf(" - sgsn_alloc_ptmsi\n");
1609
1610 /* reset the PRNG used by sgsn_alloc_ptmsi */
1611 srand(1);
1612
1613 ptmsi1 = sgsn_alloc_ptmsi();
1614 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1615
1616 ptmsi2 = sgsn_alloc_ptmsi();
1617 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1618
1619 OSMO_ASSERT(ptmsi1 != ptmsi2);
1620
1621 printf(" - Repeated Attach Request\n");
1622
1623 /* reset the PRNG, so that the same P-TMSI will be generated
1624 * again */
1625 srand(1);
1626
1627 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1628
1629 /* Create a LLE/LLME */
1630 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1631 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1632 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1633
1634 /* inject the attach request */
1635 send_0408_message(lle->llme, foreign_tlli,
1636 attach_req, ARRAY_SIZE(attach_req));
1637
1638 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1639 OSMO_ASSERT(ctx != NULL);
1640 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1641 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1642
1643 old_ptmsi = ctx->p_tmsi_old;
1644
1645 /* we expect an identity request (IMEI) */
1646 OSMO_ASSERT(sgsn_tx_counter == 1);
1647
1648 /* inject the identity response (IMEI) */
1649 send_0408_message(ctx->llme, foreign_tlli,
1650 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1651
1652 /* check that the MM context has not been removed due to a failed
1653 * authorization */
1654 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1655
1656 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1657 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1658
1659 /* we expect an attach accept */
1660 OSMO_ASSERT(sgsn_tx_counter == 1);
1661
1662 /* we ignore this and send the attach again */
1663 send_0408_message(lle->llme, foreign_tlli,
1664 attach_req, ARRAY_SIZE(attach_req));
1665
1666 /* the allocated P-TMSI should be the same */
1667 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1668 OSMO_ASSERT(ctx != NULL);
1669 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1670 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1671 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1672
1673 /* inject the attach complete */
1674 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1675 send_0408_message(ctx->llme, local_tlli,
1676 attach_compl, ARRAY_SIZE(attach_compl));
1677
1678 /* we don't expect a response */
1679 OSMO_ASSERT(sgsn_tx_counter == 0);
1680
1681 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1682 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1683 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1684
1685 printf(" - Repeated RA Update Request\n");
1686
1687 /* inject the RA update request */
1688 send_0408_message(ctx->llme, local_tlli,
1689 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1690
1691 /* we expect an RA update accept */
1692 OSMO_ASSERT(sgsn_tx_counter == 1);
1693
1694 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1695 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1696 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1697
1698 /* repeat the RA update request */
1699 send_0408_message(ctx->llme, local_tlli,
1700 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1701
1702 /* we expect an RA update accept */
1703 OSMO_ASSERT(sgsn_tx_counter == 1);
1704
1705 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1706 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1707 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1708
1709 /* inject the RA update complete */
1710 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1711 send_0408_message(ctx->llme, local_tlli,
1712 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1713
1714 /* we don't expect a response */
1715 OSMO_ASSERT(sgsn_tx_counter == 0);
1716
1717 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1718 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1719 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1720
1721 /* inject the detach */
1722 send_0408_message(ctx->llme, local_tlli,
1723 detach_req, ARRAY_SIZE(detach_req));
1724
1725 /* verify that things are gone */
1726 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1727 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1728 OSMO_ASSERT(!ictx);
1729
1730 sgsn->cfg.auth_policy = saved_auth_policy;
1731}
1732
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001733static void test_apn_matching(void)
1734{
1735 struct apn_ctx *actx, *actxs[9];
1736
1737 printf("Testing APN matching\n");
1738
1739 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1740 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1741 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1742 actxs[3] = NULL;
1743
1744 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1745 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1746 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1747 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1748
1749 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1750
1751 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1752 OSMO_ASSERT(actx == actxs[2]);
1753 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1754 OSMO_ASSERT(actx == actxs[2]);
1755 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1756 OSMO_ASSERT(actx == actxs[1]);
1757 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1758 OSMO_ASSERT(actx == actxs[1]);
1759 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1760 OSMO_ASSERT(actx == actxs[0]);
1761 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1762 OSMO_ASSERT(actx == NULL);
1763
1764 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1765 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1766 OSMO_ASSERT(actx == actxs[3]);
1767
1768 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1769 OSMO_ASSERT(actx == actxs[4]);
1770
1771 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1772 OSMO_ASSERT(actx == actxs[6]);
1773
1774 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1775 OSMO_ASSERT(actx == actxs[5]);
1776
1777 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1778 OSMO_ASSERT(actx == actxs[7]);
1779
1780 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1781 OSMO_ASSERT(actx == actxs[8]);
1782
1783 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1784 OSMO_ASSERT(actx == actxs[7]);
1785
1786 /* Free APN contexts and check how the matching changes */
1787
1788 sgsn_apn_ctx_free(actxs[7]);
1789 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1790 OSMO_ASSERT(actx == actxs[8]);
1791
1792 sgsn_apn_ctx_free(actxs[8]);
1793 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1794 OSMO_ASSERT(actx == actxs[6]);
1795
1796 sgsn_apn_ctx_free(actxs[6]);
1797 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1798 OSMO_ASSERT(actx == actxs[1]);
1799
1800 sgsn_apn_ctx_free(actxs[5]);
1801 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1802 OSMO_ASSERT(actx == actxs[4]);
1803
1804 sgsn_apn_ctx_free(actxs[4]);
1805 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1806 OSMO_ASSERT(actx == actxs[2]);
1807
1808 sgsn_apn_ctx_free(actxs[2]);
1809 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1810 OSMO_ASSERT(actx == actxs[1]);
1811
1812 sgsn_apn_ctx_free(actxs[1]);
1813 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1814 OSMO_ASSERT(actx == actxs[0]);
1815
1816 sgsn_apn_ctx_free(actxs[0]);
1817 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1818 OSMO_ASSERT(actx == actxs[3]);
1819
1820 sgsn_apn_ctx_free(actxs[3]);
1821 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1822 OSMO_ASSERT(actx == NULL);
1823}
1824
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001825struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1826 struct sgsn_subscriber_data *sdata);
1827
1828static void test_ggsn_selection(void)
1829{
1830 struct apn_ctx *actxs[4];
1831 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
1832 struct gsm_subscriber *s1;
1833 const char *imsi1 = "1234567890";
1834 struct sgsn_mm_ctx *ctx;
1835 struct gprs_ra_id raid = { 0, };
1836 uint32_t local_tlli = 0xffeeddcc;
1837 enum gsm48_gsm_cause gsm_cause;
1838 struct tlv_parsed tp;
1839 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1840 struct sgsn_subscriber_pdp_data *pdp_data;
1841
1842 printf("Testing GGSN selection\n");
1843
1844 gprs_gsup_client_send_cb = my_gprs_gsup_client_send_dummy;
1845
1846 /* Check for emptiness */
1847 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1848
1849 /* Create a context */
1850 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1851 ctx = alloc_mm_ctx(local_tlli, &raid);
1852 strncpy(ctx->imsi, imsi1, sizeof(ctx->imsi) - 1);
1853
1854 /* Allocate and attach a subscriber */
1855 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1856 assert_subscr(s1, imsi1);
1857
1858 tp.lv[GSM48_IE_GSM_APN].len = 0;
1859 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1860
1861 /* TODO: Add PDP info entries to s1 */
1862
1863 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1864 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1865 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1866
1867 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1868 actxs[0]->ggsn = ggcs[0];
1869 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1870 actxs[1]->ggsn = ggcs[1];
1871 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1872 actxs[2]->ggsn = ggcs[2];
1873
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001874 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1875 pdp_data->context_id = 1;
1876 pdp_data->pdp_type = 0x0121;
1877 strncpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str)-1);
1878
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001879 /* Resolve GGSNs */
1880
1881 tp.lv[GSM48_IE_GSM_APN].len =
1882 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1883
1884 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1885 OSMO_ASSERT(ggc != NULL);
1886 OSMO_ASSERT(ggc->id == 0);
1887
1888 tp.lv[GSM48_IE_GSM_APN].len =
1889 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1890
1891 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1892 OSMO_ASSERT(ggc != NULL);
1893 OSMO_ASSERT(ggc->id == 1);
1894
1895 tp.lv[GSM48_IE_GSM_APN].len = 0;
1896 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1897
1898 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1899 OSMO_ASSERT(ggc != NULL);
1900 OSMO_ASSERT(ggc->id == 0);
1901
1902 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1903 actxs[3]->ggsn = ggcs[2];
1904 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1905 OSMO_ASSERT(ggc != NULL);
1906 OSMO_ASSERT(ggc->id == 2);
1907
1908 sgsn_apn_ctx_free(actxs[3]);
1909 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1910
1911 tp.lv[GSM48_IE_GSM_APN].len =
1912 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1913
1914 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1915 OSMO_ASSERT(ggc == NULL);
1916 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
1917
1918 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
1919 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1920 OSMO_ASSERT(ggc == NULL);
1921 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1922
1923 /* Add PDP data entry to subscriber */
1924
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001925 strncpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str)-1);
1926
1927 tp.lv[GSM48_IE_GSM_APN].len =
1928 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1929
1930 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1931 OSMO_ASSERT(ggc != NULL);
1932 OSMO_ASSERT(ggc->id == 0);
1933
1934 tp.lv[GSM48_IE_GSM_APN].len =
1935 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1936
1937 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1938 OSMO_ASSERT(ggc == NULL);
1939 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
1940
1941 /* Cleanup */
1942
1943 subscr_put(s1);
1944 sgsn_mm_ctx_cleanup_free(ctx);
1945
1946 assert_no_subscrs();
1947
1948 sgsn_apn_ctx_free(actxs[0]);
1949 sgsn_apn_ctx_free(actxs[1]);
1950 sgsn_apn_ctx_free(actxs[2]);
1951
1952 sgsn_ggsn_ctx_free(ggcs[0]);
1953 sgsn_ggsn_ctx_free(ggcs[1]);
1954 sgsn_ggsn_ctx_free(ggcs[2]);
1955
1956 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1957}
1958
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001959static struct log_info_cat gprs_categories[] = {
1960 [DMM] = {
1961 .name = "DMM",
1962 .description = "Layer3 Mobility Management (MM)",
1963 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001964 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001965 },
1966 [DPAG] = {
1967 .name = "DPAG",
1968 .description = "Paging Subsystem",
1969 .color = "\033[1;38m",
1970 .enabled = 1, .loglevel = LOGL_NOTICE,
1971 },
1972 [DMEAS] = {
1973 .name = "DMEAS",
1974 .description = "Radio Measurement Processing",
1975 .enabled = 0, .loglevel = LOGL_NOTICE,
1976 },
1977 [DREF] = {
1978 .name = "DREF",
1979 .description = "Reference Counting",
1980 .enabled = 0, .loglevel = LOGL_NOTICE,
1981 },
1982 [DGPRS] = {
1983 .name = "DGPRS",
1984 .description = "GPRS Packet Service",
1985 .enabled = 1, .loglevel = LOGL_DEBUG,
1986 },
1987 [DNS] = {
1988 .name = "DNS",
1989 .description = "GPRS Network Service (NS)",
1990 .enabled = 1, .loglevel = LOGL_INFO,
1991 },
1992 [DBSSGP] = {
1993 .name = "DBSSGP",
1994 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1995 .enabled = 1, .loglevel = LOGL_DEBUG,
1996 },
1997 [DLLC] = {
1998 .name = "DLLC",
1999 .description = "GPRS Logical Link Control Protocol (LLC)",
2000 .enabled = 1, .loglevel = LOGL_DEBUG,
2001 },
2002 [DSNDCP] = {
2003 .name = "DSNDCP",
2004 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
2005 .enabled = 1, .loglevel = LOGL_DEBUG,
2006 },
2007};
2008
2009static struct log_info info = {
2010 .cat = gprs_categories,
2011 .num_cat = ARRAY_SIZE(gprs_categories),
2012};
2013
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002014int main(int argc, char **argv)
2015{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002016 void *osmo_sgsn_ctx;
2017
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002018 osmo_init_logging(&info);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002019 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
2020 tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
2021 tall_msgb_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "msgb");
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002022
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01002023 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002024 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01002025
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002026 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002027 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01002028 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01002029 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02002030 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01002031 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02002032 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01002033 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01002034 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01002035 test_gmm_attach_acl();
2036 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01002037 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01002038 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01002039 test_gmm_attach_subscr_gsup_auth(0);
2040 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01002041 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01002042 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01002043 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01002044 test_gmm_ptmsi_allocation();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01002045 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01002046 test_ggsn_selection();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002047 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01002048
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002049 talloc_report_full(osmo_sgsn_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01002050 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002051 OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002052 return 0;
2053}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002054
2055
2056/* stubs */
2057struct osmo_prim_hdr;
2058int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
2059{
2060 abort();
2061}