blob: 879dfe36e74be54b7c72645bf0bb150da155bfc5 [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,
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001158 };
1159
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001160 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001161
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001162 if (upd_loc_skip > 0) {
1163 upd_loc_skip -= 1;
1164 return -EAGAIN;
1165 }
1166
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001167 /* Fake an UpdateLocRes */
1168 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1169};
1170
1171
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001172static void test_gmm_attach_subscr_gsup_auth(int retry)
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001173{
1174 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1175 struct gsm_subscriber *subscr;
1176
1177 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
1178 subscr_request_update_location_cb = my_subscr_request_update_gsup_auth;
1179 subscr_request_auth_info_cb = my_subscr_request_auth_info_gsup_auth;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001180 if (retry) {
1181 upd_loc_skip = 3;
1182 auth_info_skip = 3;
1183 }
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001184
1185 subscr = gprs_subscr_get_or_create("123456789012345");
1186 subscr->authorized = 1;
1187 sgsn->cfg.require_authentication = 1;
1188 sgsn->cfg.require_update_location = 1;
1189 subscr_put(subscr);
1190
1191 printf("Auth policy 'remote', GSUP based auth: ");
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001192 test_gmm_attach(retry);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001193 assert_no_subscrs();
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001194
1195 sgsn->cfg.auth_policy = saved_auth_policy;
1196 subscr_request_update_location_cb = __real_gprs_subscr_request_update_location;
1197 subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info;
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001198 upd_loc_skip = 0;
1199 auth_info_skip = 0;
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001200}
1201
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001202int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
1203{
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001204 struct gprs_gsup_message to_peer = {0};
1205 struct gprs_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001206 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001207 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001208
1209 /* Simulate the GSUP peer */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001210 rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
1211 OSMO_ASSERT(rc >= 0);
1212 OSMO_ASSERT(to_peer.imsi[0] != 0);
1213 strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001214
1215 /* This invalidates the pointers in to_peer */
1216 msgb_free(msg);
1217
1218 switch (to_peer.message_type) {
1219 case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
1220 /* Send UPDATE_LOCATION_RESULT */
1221 return my_subscr_request_update_gsup_auth(NULL);
1222
1223 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
1224 /* Send SEND_AUTH_INFO_RESULT */
1225 return my_subscr_request_auth_info_gsup_auth(NULL);
1226
1227 case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001228 from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
1229 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001230
1231 default:
1232 if ((to_peer.message_type & 0b00000011) == 0) {
1233 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001234 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001235 from_peer.message_type = to_peer.message_type + 1;
1236 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1237 break;
1238 }
1239
1240 /* Ignore it */
1241 return 0;
1242 }
1243
1244 reply_msg = gprs_gsup_msgb_alloc();
1245 reply_msg->l2h = reply_msg->data;
1246 gprs_gsup_encode(reply_msg, &from_peer);
1247 gprs_subscr_rx_gsup_message(reply_msg);
1248 msgb_free(reply_msg);
1249
1250 return 0;
1251};
1252
1253static void test_gmm_attach_subscr_real_gsup_auth(int retry)
1254{
1255 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1256 struct gsm_subscriber *subscr;
1257
1258 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_REMOTE;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001259 gprs_gsup_client_send_cb = my_gprs_gsup_client_send;
1260
1261 sgsn->gsup_client = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client);
1262
1263 if (retry) {
1264 upd_loc_skip = 3;
1265 auth_info_skip = 3;
1266 }
1267
1268 printf("Auth policy 'remote', real GSUP based auth: ");
1269 test_gmm_attach(retry);
1270
1271 subscr = gprs_subscr_get_by_imsi("123456789012345");
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +01001272 OSMO_ASSERT(subscr == NULL);
Jacob Erlbeck058bc262015-01-13 11:46:32 +01001273 assert_no_subscrs();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001274
1275 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001276 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1277 upd_loc_skip = 0;
1278 auth_info_skip = 0;
1279 talloc_free(sgsn->gsup_client);
1280 sgsn->gsup_client = NULL;
1281}
1282
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001283/*
1284 * Test the GMM Rejects
1285 */
1286static void test_gmm_reject(void)
1287{
1288 struct gprs_ra_id raid = { 0, };
1289 struct sgsn_mm_ctx *ctx = NULL;
1290 uint32_t foreign_tlli;
1291 struct gprs_llc_lle *lle;
1292 int idx;
1293
1294 /* DTAP - Attach Request */
1295 /* Invalid MI length */
1296 static const unsigned char attach_req_inv_mi_len[] = {
1297 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1298 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1299 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1300 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1301 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1302 };
1303
1304 /* DTAP - Attach Request */
1305 /* Invalid MI type (IMEI) */
1306 static const unsigned char attach_req_inv_mi_type[] = {
1307 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1308 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1309 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1310 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1311 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1312 };
1313
1314 /* DTAP - Routing Area Update Request */
1315 static const unsigned char dtap_ra_upd_req[] = {
1316 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1317 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1318 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1319 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1320 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1321 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1322 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1323 };
1324
1325 /* DTAP - Routing Area Update Request */
1326 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1327 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1328 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1329 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1330 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1331 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1332 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1333 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1334 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1335 };
1336
1337 /* DTAP - Routing Area Update Request */
1338 /* Invalid cap length */
1339 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1340 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1341 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1342 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1343 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1344 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1345 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1346 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1347 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1348 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1349 };
1350
1351 struct test {
1352 const char *title;
1353 const unsigned char *msg;
1354 unsigned msg_len;
1355 unsigned num_resp;
1356
1357 };
1358 static struct test tests[] = {
1359 {
1360 .title = "Attach Request (invalid MI length)",
1361 .msg = attach_req_inv_mi_len,
1362 .msg_len = sizeof(attach_req_inv_mi_len),
1363 .num_resp = 1 /* Reject */
1364
1365 },
1366 {
1367 .title = "Attach Request (invalid MI type)",
1368 .msg = attach_req_inv_mi_type,
1369 .msg_len = sizeof(attach_req_inv_mi_type),
1370 .num_resp = 1 /* Reject */
1371 },
1372 {
1373 .title = "Routing Area Update Request (valid)",
1374 .msg = dtap_ra_upd_req,
1375 .msg_len = sizeof(dtap_ra_upd_req),
1376 .num_resp = 2 /* XID Reset + Reject */
1377 },
1378 {
1379 .title = "Routing Area Update Request (invalid type)",
1380 .msg = dtap_ra_upd_req_inv_type,
1381 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1382 .num_resp = 1 /* Reject */
1383 },
1384 {
1385 .title = "Routing Area Update Request (invalid CAP length)",
1386 .msg = dtap_ra_upd_req_inv_cap_len,
1387 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1388 .num_resp = 1 /* Reject */
1389 },
1390 };
1391
1392 printf("Testing GMM reject\n");
1393
1394 /* reset the PRNG used by sgsn_alloc_ptmsi */
1395 srand(1);
1396
1397 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1398
1399 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1400
1401 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1402 const struct test *test = &tests[idx];
1403 printf(" - %s\n", test->title);
1404
1405 /* Create a LLE/LLME */
1406 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1407 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1408
1409 /* Inject the Request message */
1410 send_0408_message(lle->llme, foreign_tlli,
1411 test->msg, test->msg_len);
1412
1413 /* We expect a Reject message */
1414 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1415 sgsn_tx_counter, test->num_resp);
1416 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1417
1418 /* verify that LLME/MM are removed */
1419 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1420 OSMO_ASSERT(ctx == NULL);
1421 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1422 }
1423}
1424
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001425/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001426 * Test cancellation of attached MM contexts
1427 */
1428static void test_gmm_cancel(void)
1429{
1430 struct gprs_ra_id raid = { 0, };
1431 struct sgsn_mm_ctx *ctx = NULL;
1432 struct sgsn_mm_ctx *ictx;
1433 uint32_t ptmsi1;
1434 uint32_t foreign_tlli;
1435 uint32_t local_tlli = 0;
1436 struct gprs_llc_lle *lle;
1437 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1438
1439 /* DTAP - Attach Request */
1440 /* The P-TMSI is not known by the SGSN */
1441 static const unsigned char attach_req[] = {
1442 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1443 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1444 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1445 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1446 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1447 };
1448
1449 /* DTAP - Identity Response IMEI */
1450 static const unsigned char ident_resp_imei[] = {
1451 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1452 0x56
1453 };
1454
1455 /* DTAP - Identity Response IMSI */
1456 static const unsigned char ident_resp_imsi[] = {
1457 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1458 0x54
1459 };
1460
1461 /* DTAP - Attach Complete */
1462 static const unsigned char attach_compl[] = {
1463 0x08, 0x03
1464 };
1465
1466 printf("Testing cancellation\n");
1467
1468 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1469
1470 /* reset the PRNG used by sgsn_alloc_ptmsi */
1471 srand(1);
1472
1473 ptmsi1 = sgsn_alloc_ptmsi();
1474 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1475
1476 /* reset the PRNG, so that the same P-TMSI sequence will be generated
1477 * again */
1478 srand(1);
1479
1480 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1481
1482 /* Create a LLE/LLME */
1483 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1484 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1485 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1486
1487 /* inject the attach request */
1488 send_0408_message(lle->llme, foreign_tlli,
1489 attach_req, ARRAY_SIZE(attach_req));
1490
1491 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1492 OSMO_ASSERT(ctx != NULL);
1493 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1494
1495 /* we expect an identity request (IMEI) */
1496 OSMO_ASSERT(sgsn_tx_counter == 1);
1497
1498 /* inject the identity response (IMEI) */
1499 send_0408_message(ctx->llme, foreign_tlli,
1500 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1501
1502 /* we expect an identity request (IMSI) */
1503 OSMO_ASSERT(sgsn_tx_counter == 1);
1504
1505 /* inject the identity response (IMSI) */
1506 send_0408_message(ctx->llme, foreign_tlli,
1507 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1508
1509 /* check that the MM context has not been removed due to a failed
1510 * authorization */
1511 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1512
1513 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1514
1515 /* we expect an attach accept/reject */
1516 OSMO_ASSERT(sgsn_tx_counter == 1);
1517
1518 /* this has been randomly assigned by the SGSN */
1519 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1520
1521 /* inject the attach complete */
1522 send_0408_message(ctx->llme, local_tlli,
1523 attach_compl, ARRAY_SIZE(attach_compl));
1524
1525 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1526
1527 /* we don't expect a response */
1528 OSMO_ASSERT(sgsn_tx_counter == 0);
1529
1530 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001531 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001532
1533 /* verify that things are gone */
1534 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1535 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1536 OSMO_ASSERT(!ictx);
1537
1538 sgsn->cfg.auth_policy = saved_auth_policy;
1539}
1540
1541/*
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001542 * Test the dynamic allocation of P-TMSIs
1543 */
1544static void test_gmm_ptmsi_allocation(void)
1545{
1546 struct gprs_ra_id raid = { 0, };
1547 struct sgsn_mm_ctx *ctx = NULL;
1548 struct sgsn_mm_ctx *ictx;
1549 uint32_t foreign_tlli;
1550 uint32_t ptmsi1;
1551 uint32_t ptmsi2;
1552 uint32_t old_ptmsi;
1553 uint32_t local_tlli = 0;
1554 struct gprs_llc_lle *lle;
1555 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1556
1557 /* DTAP - Attach Request (IMSI 12131415161718) */
1558 static const unsigned char attach_req[] = {
1559 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
1560 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1561 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
1562 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
1563 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
1564 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
1565 0x00,
1566 };
1567
1568 /* DTAP - Identity Response IMEI */
1569 static const unsigned char ident_resp_imei[] = {
1570 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1571 0x56
1572 };
1573
1574 /* DTAP - Attach Complete */
1575 static const unsigned char attach_compl[] = {
1576 0x08, 0x03
1577 };
1578
1579 /* DTAP - Routing Area Update Request */
1580 static const unsigned char ra_upd_req[] = {
1581 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1582 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1583 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1584 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1585 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1586 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1587 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1588 };
1589
1590 /* DTAP - Routing Area Update Complete */
1591 static const unsigned char ra_upd_complete[] = {
1592 0x08, 0x0a
1593 };
1594
1595 /* DTAP - Detach Request (MO) */
1596 /* normal detach, power_off = 1 */
1597 static const unsigned char detach_req[] = {
1598 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
1599 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
1600 };
1601
1602 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1603
1604 printf("Testing P-TMSI allocation\n");
1605
1606 printf(" - sgsn_alloc_ptmsi\n");
1607
1608 /* reset the PRNG used by sgsn_alloc_ptmsi */
1609 srand(1);
1610
1611 ptmsi1 = sgsn_alloc_ptmsi();
1612 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
1613
1614 ptmsi2 = sgsn_alloc_ptmsi();
1615 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
1616
1617 OSMO_ASSERT(ptmsi1 != ptmsi2);
1618
1619 printf(" - Repeated Attach Request\n");
1620
1621 /* reset the PRNG, so that the same P-TMSI will be generated
1622 * again */
1623 srand(1);
1624
1625 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1626
1627 /* Create a LLE/LLME */
1628 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1629 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1630 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1631
1632 /* inject the attach request */
1633 send_0408_message(lle->llme, foreign_tlli,
1634 attach_req, ARRAY_SIZE(attach_req));
1635
1636 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1637 OSMO_ASSERT(ctx != NULL);
1638 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1639 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1640
1641 old_ptmsi = ctx->p_tmsi_old;
1642
1643 /* we expect an identity request (IMEI) */
1644 OSMO_ASSERT(sgsn_tx_counter == 1);
1645
1646 /* inject the identity response (IMEI) */
1647 send_0408_message(ctx->llme, foreign_tlli,
1648 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1649
1650 /* check that the MM context has not been removed due to a failed
1651 * authorization */
1652 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1653
1654 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1655 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1656
1657 /* we expect an attach accept */
1658 OSMO_ASSERT(sgsn_tx_counter == 1);
1659
1660 /* we ignore this and send the attach again */
1661 send_0408_message(lle->llme, foreign_tlli,
1662 attach_req, ARRAY_SIZE(attach_req));
1663
1664 /* the allocated P-TMSI should be the same */
1665 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1666 OSMO_ASSERT(ctx != NULL);
1667 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1668 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
1669 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1670
1671 /* inject the attach complete */
1672 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1673 send_0408_message(ctx->llme, local_tlli,
1674 attach_compl, ARRAY_SIZE(attach_compl));
1675
1676 /* we don't expect a response */
1677 OSMO_ASSERT(sgsn_tx_counter == 0);
1678
1679 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1680 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1681 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
1682
1683 printf(" - Repeated RA Update Request\n");
1684
1685 /* inject the RA update request */
1686 send_0408_message(ctx->llme, local_tlli,
1687 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1688
1689 /* we expect an RA update accept */
1690 OSMO_ASSERT(sgsn_tx_counter == 1);
1691
1692 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1693 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1694 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1695
1696 /* repeat the RA update request */
1697 send_0408_message(ctx->llme, local_tlli,
1698 ra_upd_req, ARRAY_SIZE(ra_upd_req));
1699
1700 /* we expect an RA update accept */
1701 OSMO_ASSERT(sgsn_tx_counter == 1);
1702
1703 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
1704 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
1705 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1706
1707 /* inject the RA update complete */
1708 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
1709 send_0408_message(ctx->llme, local_tlli,
1710 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
1711
1712 /* we don't expect a response */
1713 OSMO_ASSERT(sgsn_tx_counter == 0);
1714
1715 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
1716 OSMO_ASSERT(ctx->p_tmsi_old == 0);
1717 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
1718
1719 /* inject the detach */
1720 send_0408_message(ctx->llme, local_tlli,
1721 detach_req, ARRAY_SIZE(detach_req));
1722
1723 /* verify that things are gone */
1724 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1725 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1726 OSMO_ASSERT(!ictx);
1727
1728 sgsn->cfg.auth_policy = saved_auth_policy;
1729}
1730
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001731static void test_apn_matching(void)
1732{
1733 struct apn_ctx *actx, *actxs[9];
1734
1735 printf("Testing APN matching\n");
1736
1737 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1738 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1739 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1740 actxs[3] = NULL;
1741
1742 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1743 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1744 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1745 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1746
1747 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1748
1749 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1750 OSMO_ASSERT(actx == actxs[2]);
1751 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1752 OSMO_ASSERT(actx == actxs[2]);
1753 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1754 OSMO_ASSERT(actx == actxs[1]);
1755 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1756 OSMO_ASSERT(actx == actxs[1]);
1757 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1758 OSMO_ASSERT(actx == actxs[0]);
1759 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1760 OSMO_ASSERT(actx == NULL);
1761
1762 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1763 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1764 OSMO_ASSERT(actx == actxs[3]);
1765
1766 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1767 OSMO_ASSERT(actx == actxs[4]);
1768
1769 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1770 OSMO_ASSERT(actx == actxs[6]);
1771
1772 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1773 OSMO_ASSERT(actx == actxs[5]);
1774
1775 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1776 OSMO_ASSERT(actx == actxs[7]);
1777
1778 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1779 OSMO_ASSERT(actx == actxs[8]);
1780
1781 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1782 OSMO_ASSERT(actx == actxs[7]);
1783
1784 /* Free APN contexts and check how the matching changes */
1785
1786 sgsn_apn_ctx_free(actxs[7]);
1787 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1788 OSMO_ASSERT(actx == actxs[8]);
1789
1790 sgsn_apn_ctx_free(actxs[8]);
1791 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1792 OSMO_ASSERT(actx == actxs[6]);
1793
1794 sgsn_apn_ctx_free(actxs[6]);
1795 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1796 OSMO_ASSERT(actx == actxs[1]);
1797
1798 sgsn_apn_ctx_free(actxs[5]);
1799 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1800 OSMO_ASSERT(actx == actxs[4]);
1801
1802 sgsn_apn_ctx_free(actxs[4]);
1803 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1804 OSMO_ASSERT(actx == actxs[2]);
1805
1806 sgsn_apn_ctx_free(actxs[2]);
1807 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1808 OSMO_ASSERT(actx == actxs[1]);
1809
1810 sgsn_apn_ctx_free(actxs[1]);
1811 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1812 OSMO_ASSERT(actx == actxs[0]);
1813
1814 sgsn_apn_ctx_free(actxs[0]);
1815 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1816 OSMO_ASSERT(actx == actxs[3]);
1817
1818 sgsn_apn_ctx_free(actxs[3]);
1819 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1820 OSMO_ASSERT(actx == NULL);
1821}
1822
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001823struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1824 struct sgsn_subscriber_data *sdata);
1825
1826static void test_ggsn_selection(void)
1827{
1828 struct apn_ctx *actxs[4];
1829 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
1830 struct gsm_subscriber *s1;
1831 const char *imsi1 = "1234567890";
1832 struct sgsn_mm_ctx *ctx;
1833 struct gprs_ra_id raid = { 0, };
1834 uint32_t local_tlli = 0xffeeddcc;
1835 enum gsm48_gsm_cause gsm_cause;
1836 struct tlv_parsed tp;
1837 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1838 struct sgsn_subscriber_pdp_data *pdp_data;
1839
1840 printf("Testing GGSN selection\n");
1841
1842 gprs_gsup_client_send_cb = my_gprs_gsup_client_send_dummy;
1843
1844 /* Check for emptiness */
1845 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1846
1847 /* Create a context */
1848 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1849 ctx = alloc_mm_ctx(local_tlli, &raid);
1850 strncpy(ctx->imsi, imsi1, sizeof(ctx->imsi) - 1);
1851
1852 /* Allocate and attach a subscriber */
1853 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1854 assert_subscr(s1, imsi1);
1855
1856 tp.lv[GSM48_IE_GSM_APN].len = 0;
1857 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1858
1859 /* TODO: Add PDP info entries to s1 */
1860
1861 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1862 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1863 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1864
1865 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1866 actxs[0]->ggsn = ggcs[0];
1867 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1868 actxs[1]->ggsn = ggcs[1];
1869 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1870 actxs[2]->ggsn = ggcs[2];
1871
1872 /* Resolve GGSNs */
1873
1874 tp.lv[GSM48_IE_GSM_APN].len =
1875 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1876
1877 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1878 OSMO_ASSERT(ggc != NULL);
1879 OSMO_ASSERT(ggc->id == 0);
1880
1881 tp.lv[GSM48_IE_GSM_APN].len =
1882 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1883
1884 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1885 OSMO_ASSERT(ggc != NULL);
1886 OSMO_ASSERT(ggc->id == 1);
1887
1888 tp.lv[GSM48_IE_GSM_APN].len = 0;
1889 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1890
1891 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1892 OSMO_ASSERT(ggc != NULL);
1893 OSMO_ASSERT(ggc->id == 0);
1894
1895 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1896 actxs[3]->ggsn = ggcs[2];
1897 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1898 OSMO_ASSERT(ggc != NULL);
1899 OSMO_ASSERT(ggc->id == 2);
1900
1901 sgsn_apn_ctx_free(actxs[3]);
1902 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1903
1904 tp.lv[GSM48_IE_GSM_APN].len =
1905 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1906
1907 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1908 OSMO_ASSERT(ggc == NULL);
1909 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
1910
1911 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
1912 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1913 OSMO_ASSERT(ggc == NULL);
1914 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1915
1916 /* Add PDP data entry to subscriber */
1917
1918 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1919 pdp_data->context_id = 1;
1920
1921 pdp_data->pdp_type = 0x0121;
1922 strncpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str)-1);
1923
1924 tp.lv[GSM48_IE_GSM_APN].len =
1925 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1926
1927 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1928 OSMO_ASSERT(ggc != NULL);
1929 OSMO_ASSERT(ggc->id == 0);
1930
1931 tp.lv[GSM48_IE_GSM_APN].len =
1932 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1933
1934 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause);
1935 OSMO_ASSERT(ggc == NULL);
1936 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
1937
1938 /* Cleanup */
1939
1940 subscr_put(s1);
1941 sgsn_mm_ctx_cleanup_free(ctx);
1942
1943 assert_no_subscrs();
1944
1945 sgsn_apn_ctx_free(actxs[0]);
1946 sgsn_apn_ctx_free(actxs[1]);
1947 sgsn_apn_ctx_free(actxs[2]);
1948
1949 sgsn_ggsn_ctx_free(ggcs[0]);
1950 sgsn_ggsn_ctx_free(ggcs[1]);
1951 sgsn_ggsn_ctx_free(ggcs[2]);
1952
1953 gprs_gsup_client_send_cb = __real_gprs_gsup_client_send;
1954}
1955
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001956static struct log_info_cat gprs_categories[] = {
1957 [DMM] = {
1958 .name = "DMM",
1959 .description = "Layer3 Mobility Management (MM)",
1960 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001961 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001962 },
1963 [DPAG] = {
1964 .name = "DPAG",
1965 .description = "Paging Subsystem",
1966 .color = "\033[1;38m",
1967 .enabled = 1, .loglevel = LOGL_NOTICE,
1968 },
1969 [DMEAS] = {
1970 .name = "DMEAS",
1971 .description = "Radio Measurement Processing",
1972 .enabled = 0, .loglevel = LOGL_NOTICE,
1973 },
1974 [DREF] = {
1975 .name = "DREF",
1976 .description = "Reference Counting",
1977 .enabled = 0, .loglevel = LOGL_NOTICE,
1978 },
1979 [DGPRS] = {
1980 .name = "DGPRS",
1981 .description = "GPRS Packet Service",
1982 .enabled = 1, .loglevel = LOGL_DEBUG,
1983 },
1984 [DNS] = {
1985 .name = "DNS",
1986 .description = "GPRS Network Service (NS)",
1987 .enabled = 1, .loglevel = LOGL_INFO,
1988 },
1989 [DBSSGP] = {
1990 .name = "DBSSGP",
1991 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1992 .enabled = 1, .loglevel = LOGL_DEBUG,
1993 },
1994 [DLLC] = {
1995 .name = "DLLC",
1996 .description = "GPRS Logical Link Control Protocol (LLC)",
1997 .enabled = 1, .loglevel = LOGL_DEBUG,
1998 },
1999 [DSNDCP] = {
2000 .name = "DSNDCP",
2001 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
2002 .enabled = 1, .loglevel = LOGL_DEBUG,
2003 },
2004};
2005
2006static struct log_info info = {
2007 .cat = gprs_categories,
2008 .num_cat = ARRAY_SIZE(gprs_categories),
2009};
2010
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002011int main(int argc, char **argv)
2012{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002013 void *osmo_sgsn_ctx;
2014
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002015 osmo_init_logging(&info);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002016 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
2017 tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
2018 tall_msgb_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "msgb");
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002019
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +01002020 sgsn_auth_init();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002021 gprs_subscr_init(sgsn);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01002022
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002023 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01002024 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01002025 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01002026 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02002027 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01002028 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02002029 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01002030 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01002031 test_gmm_status_no_mmctx();
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +01002032 test_gmm_attach_acl();
2033 test_gmm_attach_subscr();
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +01002034 test_gmm_attach_subscr_fake_auth();
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +01002035 test_gmm_attach_subscr_real_auth();
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01002036 test_gmm_attach_subscr_gsup_auth(0);
2037 test_gmm_attach_subscr_gsup_auth(1);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01002038 test_gmm_attach_subscr_real_gsup_auth(0);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01002039 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01002040 test_gmm_cancel();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01002041 test_gmm_ptmsi_allocation();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01002042 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01002043 test_ggsn_selection();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002044 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01002045
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002046 talloc_report_full(osmo_sgsn_ctx, stderr);
Jacob Erlbeckf0b06d82015-01-13 11:56:28 +01002047 OSMO_ASSERT(talloc_total_blocks(tall_msgb_ctx) == 1);
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01002048 OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02002049 return 0;
2050}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02002051
2052
2053/* stubs */
2054struct osmo_prim_hdr;
2055int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
2056{
2057 abort();
2058}