blob: d9b162dc2ca6fc163e4de7b9ab40a9404cd1e93a [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));
956 }
957
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100958 if (retry && sgsn_tx_counter == 0)
959 goto retry_attach_req;
960
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100961 /* we expect an attach accept/reject */
962 OSMO_ASSERT(sgsn_tx_counter == 1);
963
964 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100965 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100966
967 /* inject the attach complete */
968 send_0408_message(ctx->llme, local_tlli,
969 attach_compl, ARRAY_SIZE(attach_compl));
970
971 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
972
973 /* we don't expect a response */
974 OSMO_ASSERT(sgsn_tx_counter == 0);
975
976 /* inject the detach */
977 send_0408_message(ctx->llme, local_tlli,
978 detach_req, ARRAY_SIZE(detach_req));
979
980 /* verify that things are gone */
981 OSMO_ASSERT(count(gprs_llme_list()) == 0);
982 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
983 OSMO_ASSERT(!ictx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100984}
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100985
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100986static void test_gmm_attach_acl(void)
987{
988 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
989
990 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
991 sgsn_acl_add("123456789012345", &sgsn->cfg);
992 printf("Auth policy 'closed': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100993 test_gmm_attach(0);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100994 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100995
996 sgsn->cfg.auth_policy = saved_auth_policy;
997}
998
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100999int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001000 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001001 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001002 if (rc == -ENOTSUP) {
1003 OSMO_ASSERT(mmctx->subscr);
1004 gprs_subscr_update(mmctx->subscr);
1005 }
1006 return rc;
1007};
1008
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001009int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
1010 gprs_subscr_update(mmctx->subscr);
1011 return 0;
1012};
1013
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001014static void test_gmm_attach_subscr(void)
1015{
1016 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1017 struct gsm_subscriber *subscr;
1018
1019 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001020 subscr_request_update_location_cb = my_subscr_request_update_location;
1021 subscr_request_auth_info_cb = my_subscr_request_auth_info;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001022
1023 subscr = gprs_subscr_get_or_create("123456789012345");
1024 subscr->authorized = 1;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001025
1026 printf("Auth policy 'remote': ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001027 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001028 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001029 assert_no_subscrs();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01001030
1031 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001032 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1033 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001034}
1035
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001036int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx)
1037{
1038 /* Fake an authentication */
1039 OSMO_ASSERT(mmctx->subscr);
1040 mmctx->is_authenticated = 1;
1041 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001042
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001043 return 0;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001044};
1045
1046static void test_gmm_attach_subscr_fake_auth(void)
1047{
1048 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1049 struct gsm_subscriber *subscr;
1050
1051 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001052 subscr_request_update_location_cb = my_subscr_request_update_location;
1053 subscr_request_auth_info_cb = my_subscr_request_auth_info_fake_auth;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001054
1055 subscr = gprs_subscr_get_or_create("123456789012345");
1056 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001057 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001058 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001059
1060 printf("Auth policy 'remote', auth faked: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001061 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001062 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001063 assert_no_subscrs();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001064
1065 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001066 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1067 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
1068}
1069
1070int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
1071{
1072 struct gsm_auth_tuple at = {
1073 .sres = {0x51, 0xe5, 0x51, 0xe5},
1074 .key_seq = 0
1075 };
1076
1077 /* Fake an authentication */
1078 OSMO_ASSERT(mmctx->subscr);
1079 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
1080
1081 gprs_subscr_update_auth_info(mmctx->subscr);
1082
1083 return 0;
1084};
1085
1086static void test_gmm_attach_subscr_real_auth(void)
1087{
1088 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1089 struct gsm_subscriber *subscr;
1090
1091 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1092 subscr_request_update_location_cb = my_subscr_request_update_location;
1093 subscr_request_auth_info_cb = my_subscr_request_auth_info_real_auth;
1094
1095 subscr = gprs_subscr_get_or_create("123456789012345");
1096 subscr->authorized = 1;
Jacob Erlbeck9d4f46c2014-12-17 13:20:08 +01001097 sgsn->cfg.require_authentication = 1;
Jacob Erlbeck771573c2014-12-19 18:08:48 +01001098 sgsn->cfg.require_update_location = 1;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001099
1100 printf("Auth policy 'remote', triplet based auth: ");
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001101
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001102 test_gmm_attach(0);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001103 subscr_put(subscr);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001104 assert_no_subscrs();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01001105
1106 sgsn->cfg.auth_policy = saved_auth_policy;
1107 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1108 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01001109}
1110
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001111#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
1112 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
1113
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001114static int auth_info_skip = 0;
1115static int upd_loc_skip = 0;
1116
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001117int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx)
1118{
1119 static const uint8_t send_auth_info_res[] = {
1120 0x0a,
1121 TEST_GSUP_IMSI_LONG_IE,
1122 0x03, 0x22, /* Auth tuple */
1123 0x20, 0x10,
1124 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
1125 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
1126 0x21, 0x04,
1127 0x51, 0xe5, 0x51, 0xe5,
1128 0x22, 0x08,
1129 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1130 };
1131
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001132 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001133
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001134 if (auth_info_skip > 0) {
1135 auth_info_skip -= 1;
1136 return -EAGAIN;
1137 }
1138
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001139 /* Fake an SendAuthInfoRes */
1140 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1141
1142 return 0;
1143};
1144
1145int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1146 static const uint8_t update_location_res[] = {
1147 0x06,
1148 TEST_GSUP_IMSI_LONG_IE,
1149 0x04, 0x00, /* PDP info complete */
1150 0x05, 0x12,
1151 0x10, 0x01, 0x01,
1152 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1153 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
1154 };
1155
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001156 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001157
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001158 if (upd_loc_skip > 0) {
1159 upd_loc_skip -= 1;
1160 return -EAGAIN;
1161 }
1162
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001163 /* Fake an UpdateLocRes */
1164 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1165};
1166
1167
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001168static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001169{
1170 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1171 struct gsm_subscriber *subscr;
1172
1173 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1174 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1175 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001176 if (retry) {
1177 upd_loc_skip = 3;
1178 auth_info_skip = 3;
1179 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001180
1181 subscr = gprs_subscr_get_or_create("123456789012345");
1182 subscr->authorized = 1;
1183 sgsn->cfg.require_authentication = 1;
1184 sgsn->cfg.require_update_location = 1;
1185 subscr_put(subscr);
1186
1187 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001188 test_gmm_attach(retry);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001189 assert_no_subscrs();
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001190
1191 sgsn->cfg.auth_policy = saved_auth_policy;
1192 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1193 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001194 upd_loc_skip = 0;
1195 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001196}
1197
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001198int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1199{
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001200 struct gprs_gsup_message to_peer = {0};
1201 struct gprs_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001202 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001203 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001204
1205 /* Simulate the GSUP peer */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001206 rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1207 OSMO_ASSERT(rc >= 0);
1208 OSMO_ASSERT(to_peer.imsi[0] != 0);
1209 strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001210
1211 /* This invalidates the pointers in to_peer */
1212 msgb_free(msg);
1213
1214 switch (to_peer.message_type) {
1215 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1216 /* Send UPDATE_LOCATION_RESULT */
1217 return my_subscr_request_update_gsup_auth(NULL);
1218
1219 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1220 /* Send SEND_AUTH_INFO_RESULT */
1221 return my_subscr_request_auth_info_gsup_auth(NULL);
1222
1223 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001224 from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
1225 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001226
1227 default:
1228 if ((to_peer.message_type & 0b00000011) == 0) {
1229 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001230 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001231 from_peer.message_type = to_peer.message_type + 1;
1232 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1233 break;
1234 }
1235
1236 /* Ignore it */
1237 return 0;
1238 }
1239
1240 reply_msg = gprs_gsup_msgb_alloc();
1241 reply_msg->l2h = reply_msg->data;
1242 gprs_gsup_encode(reply_msg, &from_peer);
1243 gprs_subscr_rx_gsup_message(reply_msg);
1244 msgb_free(reply_msg);
1245
1246 return 0;
1247};
1248
1249static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1250{
1251 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1252 struct gsm_subscriber *subscr;
1253
1254 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001255 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1256
1257 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1258
1259 if (retry) {
1260 upd_loc_skip = 3;
1261 auth_info_skip = 3;
1262 }
1263
1264 printf("Auth policy 'remote', real GSUP based auth: ");
1265 test_gmm_attach(retry);
1266
1267 subscr = gprs_subscr_get_by_imsi("123456789012345");
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001268 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001269 assert_no_subscrs();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001270
1271 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001272 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1273 upd_loc_skip = 0;
1274 auth_info_skip = 0;
1275 talloc_free(sgsn->gsup_client);
1276 sgsn->gsup_client = NULL;
1277}
1278
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001279/*
1280 * Test the GMM Rejects
1281 */
1282static void test_gmm_reject(void)
1283{
1284 struct gprs_ra_id raid = { 0, };
1285 struct sgsn_mm_ctx *ctx = NULL;
1286 uint32_t foreign_tlli;
1287 struct gprs_llc_lle *lle;
1288 int idx;
1289
1290 /* DTAP - Attach Request */
1291 /* Invalid MI length */
1292 static const unsigned char attach_req_inv_mi_len[] = {
1293 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1294 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1295 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1296 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1297 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1298 };
1299
1300 /* DTAP - Attach Request */
1301 /* Invalid MI type (IMEI) */
1302 static const unsigned char attach_req_inv_mi_type[] = {
1303 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1304 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1305 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1306 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1307 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1308 };
1309
1310 /* DTAP - Routing Area Update Request */
1311 static const unsigned char dtap_ra_upd_req[] = {
1312 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1313 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1314 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1315 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1316 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1317 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1318 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1319 };
1320
1321 /* DTAP - Routing Area Update Request */
1322 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1323 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1324 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1325 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1326 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1327 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1328 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1329 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1330 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1331 };
1332
1333 /* DTAP - Routing Area Update Request */
1334 /* Invalid cap length */
1335 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1336 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1337 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1338 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1339 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1340 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1341 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1342 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1343 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1344 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1345 };
1346
1347 struct test {
1348 const char *title;
1349 const unsigned char *msg;
1350 unsigned msg_len;
1351 unsigned num_resp;
1352
1353 };
1354 static struct test tests[] = {
1355 {
1356 .title = "Attach Request (invalid MI length)",
1357 .msg = attach_req_inv_mi_len,
1358 .msg_len = sizeof(attach_req_inv_mi_len),
1359 .num_resp = 1 /* Reject */
1360
1361 },
1362 {
1363 .title = "Attach Request (invalid MI type)",
1364 .msg = attach_req_inv_mi_type,
1365 .msg_len = sizeof(attach_req_inv_mi_type),
1366 .num_resp = 1 /* Reject */
1367 },
1368 {
1369 .title = "Routing Area Update Request (valid)",
1370 .msg = dtap_ra_upd_req,
1371 .msg_len = sizeof(dtap_ra_upd_req),
1372 .num_resp = 2 /* XID Reset + Reject */
1373 },
1374 {
1375 .title = "Routing Area Update Request (invalid type)",
1376 .msg = dtap_ra_upd_req_inv_type,
1377 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1378 .num_resp = 1 /* Reject */
1379 },
1380 {
1381 .title = "Routing Area Update Request (invalid CAP length)",
1382 .msg = dtap_ra_upd_req_inv_cap_len,
1383 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1384 .num_resp = 1 /* Reject */
1385 },
1386 };
1387
1388 printf("Testing GMM reject\n");
1389
1390 /* reset the PRNG used by sgsn_alloc_ptmsi */
1391 srand(1);
1392
1393 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1394
1395 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1396
1397 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1398 const struct test *test = &tests[idx];
1399 printf(" - %s\n", test->title);
1400
1401 /* Create a LLE/LLME */
1402 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1403 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1404
1405 /* Inject the Request message */
1406 send_0408_message(lle->llme, foreign_tlli,
1407 test->msg, test->msg_len);
1408
1409 /* We expect a Reject message */
1410 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1411 sgsn_tx_counter, test->num_resp);
1412 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1413
1414 /* verify that LLME/MM are removed */
1415 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1416 OSMO_ASSERT(ctx == NULL);
1417 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1418 }
1419}
1420
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001421/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001422 * Test cancellation of attached MM contexts
1423 */
1424static void test_gmm_cancel(void)
1425{
1426 struct gprs_ra_id raid = { 0, };
1427 struct sgsn_mm_ctx *ctx = NULL;
1428 struct sgsn_mm_ctx *ictx;
1429 uint32_t ptmsi1;
1430 uint32_t foreign_tlli;
1431 uint32_t local_tlli = 0;
1432 struct gprs_llc_lle *lle;
1433 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1434
1435 /* DTAP - Attach Request */
1436 /* The P-TMSI is not known by the SGSN */
1437 static const unsigned char attach_req[] = {
1438 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1439 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1440 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1441 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1442 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1443 };
1444
1445 /* DTAP - Identity Response IMEI */
1446 static const unsigned char ident_resp_imei[] = {
1447 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1448 0x56
1449 };
1450
1451 /* DTAP - Identity Response IMSI */
1452 static const unsigned char ident_resp_imsi[] = {
1453 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1454 0x54
1455 };
1456
1457 /* DTAP - Attach Complete */
1458 static const unsigned char attach_compl[] = {
1459 0x08, 0x03
1460 };
1461
1462 printf("Testing cancellation\n");
1463
1464 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1465
1466 /* reset the PRNG used by sgsn_alloc_ptmsi */
1467 srand(1);
1468
1469 ptmsi1 = sgsn_alloc_ptmsi();
1470 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1471
1472 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1473 * again */
1474 srand(1);
1475
1476 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1477
1478 /* Create a LLE/LLME */
1479 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1480 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1481 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1482
1483 /* inject the attach request */
1484 send_0408_message(lle->llme, foreign_tlli,
1485 attach_req, ARRAY_SIZE(attach_req));
1486
1487 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1488 OSMO_ASSERT(ctx != NULL);
1489 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1490
1491 /* we expect an identity request (IMEI) */
1492 OSMO_ASSERT(sgsn_tx_counter == 1);
1493
1494 /* inject the identity response (IMEI) */
1495 send_0408_message(ctx->llme, foreign_tlli,
1496 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1497
1498 /* we expect an identity request (IMSI) */
1499 OSMO_ASSERT(sgsn_tx_counter == 1);
1500
1501 /* inject the identity response (IMSI) */
1502 send_0408_message(ctx->llme, foreign_tlli,
1503 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1504
1505 /* check that the MM context has not been removed due to a failed
1506 * authorization */
1507 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1508
1509 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1510
1511 /* we expect an attach accept/reject */
1512 OSMO_ASSERT(sgsn_tx_counter == 1);
1513
1514 /* this has been randomly assigned by the SGSN */
1515 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1516
1517 /* inject the attach complete */
1518 send_0408_message(ctx->llme, local_tlli,
1519 attach_compl, ARRAY_SIZE(attach_compl));
1520
1521 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1522
1523 /* we don't expect a response */
1524 OSMO_ASSERT(sgsn_tx_counter == 0);
1525
1526 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001527 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001528
1529 /* verify that things are gone */
1530 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1531 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1532 OSMO_ASSERT(!ictx);
1533
1534 sgsn->cfg.auth_policy = saved_auth_policy;
1535}
1536
1537/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001538 * Test the dynamic allocation of P-TMSIs
1539 */
1540static void test_gmm_ptmsi_allocation(void)
1541{
1542 struct gprs_ra_id raid = { 0, };
1543 struct sgsn_mm_ctx *ctx = NULL;
1544 struct sgsn_mm_ctx *ictx;
1545 uint32_t foreign_tlli;
1546 uint32_t ptmsi1;
1547 uint32_t ptmsi2;
1548 uint32_t old_ptmsi;
1549 uint32_t local_tlli = 0;
1550 struct gprs_llc_lle *lle;
1551 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1552
1553 /* DTAP - Attach Request (IMSI 12131415161718) */
1554 static const unsigned char attach_req[] = {
1555 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1556 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1557 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1558 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1559 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1560 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1561 0x00,
1562 };
1563
1564 /* DTAP - Identity Response IMEI */
1565 static const unsigned char ident_resp_imei[] = {
1566 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1567 0x56
1568 };
1569
1570 /* DTAP - Attach Complete */
1571 static const unsigned char attach_compl[] = {
1572 0x08, 0x03
1573 };
1574
1575 /* DTAP - Routing Area Update Request */
1576 static const unsigned char ra_upd_req[] = {
1577 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1578 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1579 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1580 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1581 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1582 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1583 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1584 };
1585
1586 /* DTAP - Routing Area Update Complete */
1587 static const unsigned char ra_upd_complete[] = {
1588 0x08, 0x0a
1589 };
1590
1591 /* DTAP - Detach Request (MO) */
1592 /* normal detach, power_off = 1 */
1593 static const unsigned char detach_req[] = {
1594 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1595 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1596 };
1597
1598 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1599
1600 printf("Testing P-TMSI allocation\n");
1601
1602 printf(" - sgsn_alloc_ptmsi\n");
1603
1604 /* reset the PRNG used by sgsn_alloc_ptmsi */
1605 srand(1);
1606
1607 ptmsi1 = sgsn_alloc_ptmsi();
1608 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1609
1610 ptmsi2 = sgsn_alloc_ptmsi();
1611 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1612
1613 OSMO_ASSERT(ptmsi1 != ptmsi2);
1614
1615 printf(" - Repeated Attach Request\n");
1616
1617 /* reset the PRNG, so that the same P-TMSI will be generated
1618 * again */
1619 srand(1);
1620
1621 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1622
1623 /* Create a LLE/LLME */
1624 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1625 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1626 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1627
1628 /* inject the attach request */
1629 send_0408_message(lle->llme, foreign_tlli,
1630 attach_req, ARRAY_SIZE(attach_req));
1631
1632 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1633 OSMO_ASSERT(ctx != NULL);
1634 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1635 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1636
1637 old_ptmsi = ctx->p_tmsi_old;
1638
1639 /* we expect an identity request (IMEI) */
1640 OSMO_ASSERT(sgsn_tx_counter == 1);
1641
1642 /* inject the identity response (IMEI) */
1643 send_0408_message(ctx->llme, foreign_tlli,
1644 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1645
1646 /* check that the MM context has not been removed due to a failed
1647 * authorization */
1648 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1649
1650 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1651 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1652
1653 /* we expect an attach accept */
1654 OSMO_ASSERT(sgsn_tx_counter == 1);
1655
1656 /* we ignore this and send the attach again */
1657 send_0408_message(lle->llme, foreign_tlli,
1658 attach_req, ARRAY_SIZE(attach_req));
1659
1660 /* the allocated P-TMSI should be the same */
1661 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1662 OSMO_ASSERT(ctx != NULL);
1663 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1664 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1665 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1666
1667 /* inject the attach complete */
1668 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1669 send_0408_message(ctx->llme, local_tlli,
1670 attach_compl, ARRAY_SIZE(attach_compl));
1671
1672 /* we don't expect a response */
1673 OSMO_ASSERT(sgsn_tx_counter == 0);
1674
1675 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1676 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1677 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1678
1679 printf(" - Repeated RA Update Request\n");
1680
1681 /* inject the RA update request */
1682 send_0408_message(ctx->llme, local_tlli,
1683 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1684
1685 /* we expect an RA update accept */
1686 OSMO_ASSERT(sgsn_tx_counter == 1);
1687
1688 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1689 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1690 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1691
1692 /* repeat the RA update request */
1693 send_0408_message(ctx->llme, local_tlli,
1694 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1695
1696 /* we expect an RA update accept */
1697 OSMO_ASSERT(sgsn_tx_counter == 1);
1698
1699 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1700 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1701 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1702
1703 /* inject the RA update complete */
1704 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1705 send_0408_message(ctx->llme, local_tlli,
1706 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1707
1708 /* we don't expect a response */
1709 OSMO_ASSERT(sgsn_tx_counter == 0);
1710
1711 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1712 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1713 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1714
1715 /* inject the detach */
1716 send_0408_message(ctx->llme, local_tlli,
1717 detach_req, ARRAY_SIZE(detach_req));
1718
1719 /* verify that things are gone */
1720 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1721 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1722 OSMO_ASSERT(!ictx);
1723
1724 sgsn->cfg.auth_policy = saved_auth_policy;
1725}
1726
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001727static void test_apn_matching(void)
1728{
1729 struct apn_ctx *actx, *actxs[9];
1730
1731 printf("Testing APN matching\n");
1732
1733 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1734 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1735 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1736 actxs[3] = NULL;
1737
1738 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1739 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1740 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1741 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1742
1743 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1744
1745 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1746 OSMO_ASSERT(actx == actxs[2]);
1747 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1748 OSMO_ASSERT(actx == actxs[2]);
1749 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1750 OSMO_ASSERT(actx == actxs[1]);
1751 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1752 OSMO_ASSERT(actx == actxs[1]);
1753 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1754 OSMO_ASSERT(actx == actxs[0]);
1755 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1756 OSMO_ASSERT(actx == NULL);
1757
1758 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1759 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1760 OSMO_ASSERT(actx == actxs[3]);
1761
1762 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1763 OSMO_ASSERT(actx == actxs[4]);
1764
1765 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1766 OSMO_ASSERT(actx == actxs[6]);
1767
1768 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1769 OSMO_ASSERT(actx == actxs[5]);
1770
1771 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1772 OSMO_ASSERT(actx == actxs[7]);
1773
1774 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1775 OSMO_ASSERT(actx == actxs[8]);
1776
1777 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1778 OSMO_ASSERT(actx == actxs[7]);
1779
1780 /* Free APN contexts and check how the matching changes */
1781
1782 sgsn_apn_ctx_free(actxs[7]);
1783 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1784 OSMO_ASSERT(actx == actxs[8]);
1785
1786 sgsn_apn_ctx_free(actxs[8]);
1787 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1788 OSMO_ASSERT(actx == actxs[6]);
1789
1790 sgsn_apn_ctx_free(actxs[6]);
1791 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1792 OSMO_ASSERT(actx == actxs[1]);
1793
1794 sgsn_apn_ctx_free(actxs[5]);
1795 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1796 OSMO_ASSERT(actx == actxs[4]);
1797
1798 sgsn_apn_ctx_free(actxs[4]);
1799 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1800 OSMO_ASSERT(actx == actxs[2]);
1801
1802 sgsn_apn_ctx_free(actxs[2]);
1803 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1804 OSMO_ASSERT(actx == actxs[1]);
1805
1806 sgsn_apn_ctx_free(actxs[1]);
1807 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1808 OSMO_ASSERT(actx == actxs[0]);
1809
1810 sgsn_apn_ctx_free(actxs[0]);
1811 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1812 OSMO_ASSERT(actx == actxs[3]);
1813
1814 sgsn_apn_ctx_free(actxs[3]);
1815 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1816 OSMO_ASSERT(actx == NULL);
1817}
1818
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001819struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1820 struct sgsn_subscriber_data *sdata);
1821
1822static void test_ggsn_selection(void)
1823{
1824 struct apn_ctx *actxs[4];
1825 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
1826 struct gsm_subscriber *s1;
1827 const char *imsi1 = "1234567890";
1828 struct sgsn_mm_ctx *ctx;
1829 struct gprs_ra_id raid = { 0, };
1830 uint32_t local_tlli = 0xffeeddcc;
1831 enum gsm48_gsm_cause gsm_cause;
1832 struct tlv_parsed tp;
1833 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1834 struct sgsn_subscriber_pdp_data *pdp_data;
1835
1836 printf("Testing GGSN selection\n");
1837
1838 gprs_gsup_client_send_cb = my_gprs_gsup_client_send_dummy;
1839
1840 /* Check for emptiness */
1841 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1842
1843 /* Create a context */
1844 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1845 ctx = alloc_mm_ctx(local_tlli, &raid);
1846 strncpy(ctx->imsi, imsi1, sizeof(ctx->imsi) - 1);
1847
1848 /* Allocate and attach a subscriber */
1849 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1850 assert_subscr(s1, imsi1);
1851
1852 tp.lv[GSM48_IE_GSM_APN].len = 0;
1853 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1854
1855 /* TODO: Add PDP info entries to s1 */
1856
1857 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1858 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1859 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1860
1861 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1862 actxs[0]->ggsn = ggcs[0];
1863 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1864 actxs[1]->ggsn = ggcs[1];
1865 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1866 actxs[2]->ggsn = ggcs[2];
1867
1868 /* Resolve GGSNs */
1869
1870 tp.lv[GSM48_IE_GSM_APN].len =
1871 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1872
1873 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1874 OSMO_ASSERT(ggc != NULL);
1875 OSMO_ASSERT(ggc->id == 0);
1876
1877 tp.lv[GSM48_IE_GSM_APN].len =
1878 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1879
1880 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1881 OSMO_ASSERT(ggc != NULL);
1882 OSMO_ASSERT(ggc->id == 1);
1883
1884 tp.lv[GSM48_IE_GSM_APN].len = 0;
1885 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1886
1887 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1888 OSMO_ASSERT(ggc != NULL);
1889 OSMO_ASSERT(ggc->id == 0);
1890
1891 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1892 actxs[3]->ggsn = ggcs[2];
1893 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1894 OSMO_ASSERT(ggc != NULL);
1895 OSMO_ASSERT(ggc->id == 2);
1896
1897 sgsn_apn_ctx_free(actxs[3]);
1898 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1899
1900 tp.lv[GSM48_IE_GSM_APN].len =
1901 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1902
1903 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1904 OSMO_ASSERT(ggc == NULL);
1905 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
1906
1907 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
1908 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1909 OSMO_ASSERT(ggc == NULL);
1910 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1911
1912 /* Add PDP data entry to subscriber */
1913
1914 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1915 pdp_data->context_id = 1;
1916
1917 pdp_data->pdp_type = 0x0121;
1918 strncpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str)-1);
1919
1920 tp.lv[GSM48_IE_GSM_APN].len =
1921 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1922
1923 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1924 OSMO_ASSERT(ggc != NULL);
1925 OSMO_ASSERT(ggc->id == 0);
1926
1927 tp.lv[GSM48_IE_GSM_APN].len =
1928 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1929
1930 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1931 OSMO_ASSERT(ggc == NULL);
1932 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
1933
1934 /* Cleanup */
1935
1936 subscr_put(s1);
1937 sgsn_mm_ctx_cleanup_free(ctx);
1938
1939 assert_no_subscrs();
1940
1941 sgsn_apn_ctx_free(actxs[0]);
1942 sgsn_apn_ctx_free(actxs[1]);
1943 sgsn_apn_ctx_free(actxs[2]);
1944
1945 sgsn_ggsn_ctx_free(ggcs[0]);
1946 sgsn_ggsn_ctx_free(ggcs[1]);
1947 sgsn_ggsn_ctx_free(ggcs[2]);
1948
1949 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1950}
1951
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001952static struct log_info_cat gprs_categories[] = {
1953 [DMM] = {
1954 .name = "DMM",
1955 .description = "Layer3 Mobility Management (MM)",
1956 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001957 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001958 },
1959 [DPAG] = {
1960 .name = "DPAG",
1961 .description = "Paging Subsystem",
1962 .color = "\033[1;38m",
1963 .enabled = 1, .loglevel = LOGL_NOTICE,
1964 },
1965 [DMEAS] = {
1966 .name = "DMEAS",
1967 .description = "Radio Measurement Processing",
1968 .enabled = 0, .loglevel = LOGL_NOTICE,
1969 },
1970 [DREF] = {
1971 .name = "DREF",
1972 .description = "Reference Counting",
1973 .enabled = 0, .loglevel = LOGL_NOTICE,
1974 },
1975 [DGPRS] = {
1976 .name = "DGPRS",
1977 .description = "GPRS Packet Service",
1978 .enabled = 1, .loglevel = LOGL_DEBUG,
1979 },
1980 [DNS] = {
1981 .name = "DNS",
1982 .description = "GPRS Network Service (NS)",
1983 .enabled = 1, .loglevel = LOGL_INFO,
1984 },
1985 [DBSSGP] = {
1986 .name = "DBSSGP",
1987 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1988 .enabled = 1, .loglevel = LOGL_DEBUG,
1989 },
1990 [DLLC] = {
1991 .name = "DLLC",
1992 .description = "GPRS Logical Link Control Protocol (LLC)",
1993 .enabled = 1, .loglevel = LOGL_DEBUG,
1994 },
1995 [DSNDCP] = {
1996 .name = "DSNDCP",
1997 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1998 .enabled = 1, .loglevel = LOGL_DEBUG,
1999 },
2000};
2001
2002static struct log_info info = {
2003 .cat = gprs_categories,
2004 .num_cat = ARRAY_SIZE(gprs_categories),
2005};
2006
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002007int main(int argc, char **argv)
2008{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002009 void *osmo_sgsn_ctx;
2010
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002011 osmo_init_logging(&info);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002012 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
2013 tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
2014 tall_msgb_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "msgb");
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002015
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01002016 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002017 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01002018
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002019 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002020 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01002021 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01002022 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02002023 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01002024 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02002025 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01002026 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01002027 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01002028 test_gmm_attach_acl();
2029 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01002030 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01002031 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01002032 test_gmm_attach_subscr_gsup_auth(0);
2033 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01002034 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01002035 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01002036 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01002037 test_gmm_ptmsi_allocation();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01002038 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01002039 test_ggsn_selection();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002040 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01002041
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002042 talloc_report_full(osmo_sgsn_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01002043 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002044 OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002045 return 0;
2046}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002047
2048
2049/* stubs */
2050struct osmo_prim_hdr;
2051int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
2052{
2053 abort();
2054}