blob: 3e86266e7aa7316284901d14872ae00f326e0813 [file] [log] [blame]
Holger Hans Peter Freyther232f6212014-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
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020022#include <osmocom/sgsn/gprs_llc.h>
23#include <osmocom/sgsn/sgsn.h>
24#include <osmocom/sgsn/gprs_gmm.h>
25#include <osmocom/sgsn/debug.h>
26#include <osmocom/sgsn/gprs_subscriber.h>
Harald Welte4e349d62016-04-25 19:07:34 +020027#include <osmocom/gsm/gsup.h>
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020028#include <osmocom/sgsn/gsup_client.h>
29#include <osmocom/sgsn/gprs_utils.h>
30#include <osmocom/sgsn/gprs_gb_parse.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020031
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010032#include <osmocom/gprs/gprs_bssgp.h>
33
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020034#include <osmocom/gsm/gsm_utils.h>
35
36#include <osmocom/core/application.h>
37#include <osmocom/core/msgb.h>
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010038#include <osmocom/core/rate_ctr.h>
Neels Hofmeyr64a40bf2017-01-13 03:10:54 +010039#include <osmocom/core/utils.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020040
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +020041#include <stdio.h>
42
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020043void *tall_bsc_ctx;
44static struct sgsn_instance sgsn_inst = {
45 .config_file = "osmo_sgsn.cfg",
46 .cfg = {
47 .gtp_statedir = "./",
Jacob Erlbeckd7b77732014-11-04 10:08:37 +010048 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020049 },
50};
51struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010052unsigned sgsn_tx_counter = 0;
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020053struct msgb *last_msg = NULL;
54struct gprs_gb_parse_context last_dl_parse_ctx;
55
56static void reset_last_msg()
57{
58 if (last_msg)
59 msgb_free(last_msg);
60
61 last_msg = NULL;
62 memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
63}
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010064
Jacob Erlbeck515fc332015-10-12 19:36:31 +020065static void cleanup_test()
66{
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020067 reset_last_msg();
68}
69
70static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
71{
72 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
73
74 if (parse_ctx->new_ptmsi_enc)
75 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
76
77 return new_ptmsi;
Jacob Erlbeck515fc332015-10-12 19:36:31 +020078}
79
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010080/* override */
81int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
82 struct bssgp_dl_ud_par *dup)
83{
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020084 int rc;
85
86 reset_last_msg();
87
88 last_msg = msg;
89 OSMO_ASSERT(msgb_data(last_msg) != NULL);
90
91 rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
92 &last_dl_parse_ctx);
93
94 fprintf(stderr, "Got DL LLC message: %s\n",
95 gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
96
97 OSMO_ASSERT(rc > 0);
98
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010099 sgsn_tx_counter += 1;
100 return 0;
101}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200102
Maxca7be8a2017-11-01 13:28:38 +0100103/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
104int __real_osmo_get_rand_id(uint8_t *data, size_t len);
105int mock_osmo_get_rand_id(uint8_t *data, size_t len);
106int (*osmo_get_rand_id_cb)(uint8_t *, size_t) =
107 &mock_osmo_get_rand_id;
Max9943d7a2016-07-05 15:19:12 +0200108
Maxca7be8a2017-11-01 13:28:38 +0100109int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Max9943d7a2016-07-05 15:19:12 +0200110{
Maxca7be8a2017-11-01 13:28:38 +0100111 return (*osmo_get_rand_id_cb)(buf, num);
Max9943d7a2016-07-05 15:19:12 +0200112}
113/* make results of A&C ref predictable */
Maxca7be8a2017-11-01 13:28:38 +0100114int mock_osmo_get_rand_id(uint8_t *buf, size_t num)
Max9943d7a2016-07-05 15:19:12 +0200115{
116 if (num > 1)
Maxca7be8a2017-11-01 13:28:38 +0100117 return __real_osmo_get_rand_id(buf, num);
Max9943d7a2016-07-05 15:19:12 +0200118 buf[0] = 0;
119 return 1;
120}
121
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100122/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100123void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
124void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100125 &__real_sgsn_update_subscriber_data;
126
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100127void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100128{
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100129 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100130}
131
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100132/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
133int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
134int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
135 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100136
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100137int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
138 return (*subscr_request_update_location_cb)(mmctx);
139};
140
141/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
Pau Espin Pedrol78a62a52017-08-16 11:30:01 +0200142int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
143int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) =
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100144 &__real_gprs_subscr_request_auth_info;
145
Pau Espin Pedrol78a62a52017-08-16 11:30:01 +0200146int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
147 return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100148};
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100149
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +0100150/* override, requires '-Wl,--wrap=gsup_client_send' */
151int __real_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
152int (*gsup_client_send_cb)(struct gsup_client *gsupc, struct msgb *msg) =
153 &__real_gsup_client_send;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100154
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +0100155int __wrap_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100156{
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +0100157 return (*gsup_client_send_cb)(gsupc, msg);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100158};
159
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200160static int count(struct llist_head *head)
161{
162 struct llist_head *cur;
163 int count = 0;
164
165 llist_for_each(cur, head)
166 count += 1;
167
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100168 return count;
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200169}
170
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200171static struct msgb *create_msg(const uint8_t *data, size_t len)
172{
173 struct msgb *msg = msgb_alloc(len + 8, "test message");
174 msg->l1h = msgb_put(msg, 8);
175 msg->l2h = msgb_put(msg, len);
176 memcpy(msg->l2h, data, len);
177
178 msgb_bcid(msg) = msg->l1h;
179 msgb_gmmh(msg) = msg->l2h;
180 return msg;
181}
182
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100183/*
184 * Create a context and search for it
185 */
186static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
187{
188 struct sgsn_mm_ctx *ctx, *ictx;
189 struct gprs_llc_lle *lle;
190 int old_count = count(gprs_llme_list());
191
192 lle = gprs_lle_get_or_create(tlli, 3);
Alexander Couzens1c7869e2017-02-04 06:01:00 +0100193 ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
Alexander Couzens5e33f442017-01-31 15:34:26 +0100194 ctx->gmm_state = GMM_REGISTERED_NORMAL;
Harald Weltec28dc2f2015-12-25 19:12:21 +0100195 ctx->gb.llme = lle->llme;
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100196
197 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
198 OSMO_ASSERT(ictx == ctx);
199
200 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
201
202 return ctx;
203}
204
Jacob Erlbeck75488292014-10-29 10:31:18 +0100205static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100206 const struct gprs_ra_id *bssgp_raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100207 const uint8_t *data, size_t data_len)
208{
209 struct msgb *msg;
210
Jacob Erlbeck28c28f92015-10-12 19:36:32 +0200211 reset_last_msg();
Jacob Erlbeck75488292014-10-29 10:31:18 +0100212 sgsn_tx_counter = 0;
213
214 msg = create_msg(data, data_len);
215 msgb_tlli(msg) = tlli;
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100216 bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
Max4bc28212016-07-06 11:59:18 +0200217 gsm0408_gprs_rcvmsg_gb(msg, llme, false);
Jacob Erlbeck75488292014-10-29 10:31:18 +0100218 msgb_free(msg);
219}
220
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200221static void test_llme(void)
222{
223 struct gprs_llc_lle *lle, *lle_copy;
224 uint32_t local_tlli;
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200225
226 printf("Testing LLME allocations\n");
227 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200228
229 /* initial state */
230 OSMO_ASSERT(count(gprs_llme_list()) == 0);
231
232 /* Create a new entry */
233 lle = gprs_lle_get_or_create(local_tlli, 3);
234 OSMO_ASSERT(lle);
235 OSMO_ASSERT(count(gprs_llme_list()) == 1);
236
237 /* No new entry is created */
238 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
239 OSMO_ASSERT(lle == lle_copy);
240 OSMO_ASSERT(count(gprs_llme_list()) == 1);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200241
242 /* unassign which should delete it*/
Maxa86f5c02016-06-28 17:39:20 +0200243 gprs_llgmm_unassign(lle->llme);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200244
245 /* Check that everything was cleaned up */
246 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200247
248 cleanup_test();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200249}
250
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100251struct gprs_subscr *last_updated_subscr = NULL;
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100252void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100253{
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100254 OSMO_ASSERT(mmctx);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100255 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100256 __func__, mmctx, mmctx->subscr);
257 last_updated_subscr = mmctx->subscr;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100258}
259
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100260static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
Jacob Erlbecka695d242015-01-09 11:59:50 +0100261{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100262 struct gprs_subscr *sfound;
Jacob Erlbeckf3df29d2015-01-19 08:57:07 +0100263 OSMO_ASSERT(subscr);
264 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100265
266 sfound = gprs_subscr_get_by_imsi(imsi);
267 OSMO_ASSERT(sfound == subscr);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100268
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100269 gprs_subscr_put(sfound);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100270}
271
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100272static void show_subscrs(FILE *out)
273{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100274 struct gprs_subscr *subscr;
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100275
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100276 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100277 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100278 "use count: %d\n",
279 subscr->imsi, subscr->use_count);
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100280 }
281}
282
283static void assert_no_subscrs()
284{
285 show_subscrs(stdout);
286 fflush(stdout);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100287 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100288}
289
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100290#define VERBOSE_ASSERT(val, expect_op, fmt) \
291 do { \
292 printf(#val " == " fmt "\n", (val)); \
293 OSMO_ASSERT((val) expect_op); \
294 } while (0);
295
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100296static void test_subscriber(void)
297{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100298 struct gprs_subscr *s1, *s2, *s3;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100299 const char *imsi1 = "1234567890";
300 const char *imsi2 = "9876543210";
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100301 const char *imsi3 = "5656565656";
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100302
303 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
304
305 printf("Testing core subscriber data API\n");
306
307 /* Check for emptiness */
308 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
309 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100310 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100311 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100312
313 /* Allocate entry 1 */
314 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100315 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
316 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka695d242015-01-09 11:59:50 +0100317 assert_subscr(s1, imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100318 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100319 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100320
321 /* Allocate entry 2 */
322 s2 = gprs_subscr_get_or_create(imsi2);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100323 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
324 s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka695d242015-01-09 11:59:50 +0100325
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100326 /* Allocate entry 3 */
327 s3 = gprs_subscr_get_or_create(imsi3);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100328 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100329
Jacob Erlbecka695d242015-01-09 11:59:50 +0100330 /* Check entries */
331 assert_subscr(s1, imsi1);
332 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100333 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100334
335 /* Update entry 1 */
336 last_updated_subscr = NULL;
337 gprs_subscr_update(s1);
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100338 OSMO_ASSERT(last_updated_subscr == NULL);
339 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100340 OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100341
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100342 /* There is no subscriber cache. Verify it */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100343 gprs_subscr_cleanup(s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100344 gprs_subscr_put(s1);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100345 s1 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100346 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
347 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100348
Jacob Erlbecka695d242015-01-09 11:59:50 +0100349 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100350 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100351
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100352 /* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100353 gprs_subscr_cleanup(s2);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100354 gprs_subscr_put(s2);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100355 s2 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100356 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100357 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
358 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100359 assert_subscr(s3, imsi3);
360
361 /* Try to delete entry 3 */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100362 gprs_subscr_cleanup(s3);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100363 gprs_subscr_put(s3);
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100364 s3 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100365 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100366 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100367
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100368 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100369
370 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200371
372 cleanup_test();
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100373}
374
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100375static void test_auth_triplets(void)
376{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100377 struct gprs_subscr *s1, *s1found;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100378 const char *imsi1 = "1234567890";
379 struct gsm_auth_tuple *at;
380 struct sgsn_mm_ctx *ctx;
381 struct gprs_ra_id raid = { 0, };
382 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100383
384 printf("Testing authentication triplet handling\n");
385
386 /* Check for emptiness */
387 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
388
389 /* Allocate entry 1 */
390 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100391 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100392 s1found = gprs_subscr_get_by_imsi(imsi1);
393 OSMO_ASSERT(s1found == s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100394 gprs_subscr_put(s1found);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100395
396 /* Create a context */
397 OSMO_ASSERT(count(gprs_llme_list()) == 0);
398 ctx = alloc_mm_ctx(local_tlli, &raid);
399
400 /* Attach s1 to ctx */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100401 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100402 ctx->subscr->sgsn_data->mm = ctx;
403
404 /* Try to get auth tuple */
405 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
406 OSMO_ASSERT(at == NULL);
407
408 /* Add triplets */
409 s1->sgsn_data->auth_triplets[0].key_seq = 0;
410 s1->sgsn_data->auth_triplets[1].key_seq = 1;
411 s1->sgsn_data->auth_triplets[2].key_seq = 2;
412
413 /* Try to get auth tuple */
414 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
415 OSMO_ASSERT(at != NULL);
416 OSMO_ASSERT(at->key_seq == 0);
417 OSMO_ASSERT(at->use_count == 1);
418 at = sgsn_auth_get_tuple(ctx, at->key_seq);
419 OSMO_ASSERT(at != NULL);
420 OSMO_ASSERT(at->key_seq == 1);
421 OSMO_ASSERT(at->use_count == 1);
422 at = sgsn_auth_get_tuple(ctx, at->key_seq);
423 OSMO_ASSERT(at != NULL);
424 OSMO_ASSERT(at->key_seq == 2);
425 OSMO_ASSERT(at->use_count == 1);
426 at = sgsn_auth_get_tuple(ctx, at->key_seq);
427 OSMO_ASSERT(at == NULL);
428
429 /* Free MM context and subscriber */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100430 gprs_subscr_put(s1);
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100431 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100432 s1found = gprs_subscr_get_by_imsi(imsi1);
433 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200434
435 cleanup_test();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100436}
437
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100438#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
439
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100440static int rx_gsup_message(const uint8_t *data, size_t data_len)
441{
442 struct msgb *msg;
443 int rc;
444
445 msg = msgb_alloc(1024, __func__);
446 msg->l2h = msgb_put(msg, data_len);
447 OSMO_ASSERT(msg->l2h != NULL);
448 memcpy(msg->l2h, data, data_len);
449 rc = gprs_subscr_rx_gsup_message(msg);
450 msgb_free(msg);
451
452 return rc;
453}
454
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100455static void test_subscriber_gsup(void)
456{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100457 struct gprs_subscr *s1, *s1found;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100458 const char *imsi1 = "1234567890";
459 struct sgsn_mm_ctx *ctx;
460 struct gprs_ra_id raid = { 0, };
461 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100462 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100463 int rc;
464
465 static const uint8_t send_auth_info_res[] = {
466 0x0a,
467 TEST_GSUP_IMSI1_IE,
468 0x03, 0x22, /* Auth tuple */
469 0x20, 0x10,
470 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
471 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
472 0x21, 0x04,
473 0x21, 0x22, 0x23, 0x24,
474 0x22, 0x08,
475 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
476 0x03, 0x22, /* Auth tuple */
477 0x20, 0x10,
478 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
479 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
480 0x21, 0x04,
481 0xa1, 0xa2, 0xa3, 0xa4,
482 0x22, 0x08,
483 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
484 };
485
486 static const uint8_t send_auth_info_err[] = {
487 0x09,
488 TEST_GSUP_IMSI1_IE,
489 0x02, 0x01, 0x07 /* GPRS not allowed */
490 };
491
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400492#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
493
494 static const uint8_t s1_msisdn[] = { MSISDN };
495
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100496 static const uint8_t update_location_res[] = {
497 0x06,
498 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400499 0x08, 0x09, MSISDN,
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100500 0x04, 0x00, /* PDP info complete */
501 0x05, 0x12,
502 0x10, 0x01, 0x01,
503 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
504 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
505 0x05, 0x11,
506 0x10, 0x01, 0x02,
507 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
508 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
509 };
510
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400511#undef MSISDN
512
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100513 static const uint8_t update_location_err[] = {
514 0x05,
515 TEST_GSUP_IMSI1_IE,
516 0x02, 0x01, 0x07 /* GPRS not allowed */
517 };
518
519 static const uint8_t location_cancellation_req[] = {
520 0x1c,
521 TEST_GSUP_IMSI1_IE,
522 0x06, 0x01, 0x00,
523 };
524
Jacob Erlbecke7fea452015-04-07 17:49:48 +0200525 static const uint8_t location_cancellation_req_withdraw[] = {
526 0x1c,
527 TEST_GSUP_IMSI1_IE,
528 0x06, 0x01, 0x01,
529 };
530
Jacob Erlbeck00b8b912015-01-08 15:29:01 +0100531 static const uint8_t location_cancellation_req_other[] = {
532 0x1c,
533 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
534 0x06, 0x01, 0x00,
535 };
536
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100537 static const uint8_t purge_ms_err[] = {
538 0x0d,
539 TEST_GSUP_IMSI1_IE,
540 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
541 };
542
Jacob Erlbeck9ca3ace2015-01-29 14:17:51 +0100543 static const uint8_t purge_ms_err_no_cause[] = {
544 0x0d,
545 TEST_GSUP_IMSI1_IE,
546 };
547
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100548 static const uint8_t purge_ms_res[] = {
549 0x0e,
550 TEST_GSUP_IMSI1_IE,
551 0x07, 0x00,
552 };
553
554
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100555 static const uint8_t insert_data_req[] = {
556 0x10,
557 TEST_GSUP_IMSI1_IE,
558 0x05, 0x11,
559 0x10, 0x01, 0x03,
560 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
561 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
562 };
563
564 static const uint8_t delete_data_req[] = {
565 0x14,
566 TEST_GSUP_IMSI1_IE,
567 0x10, 0x01, 0x03,
568 };
569
Neels Hofmeyr2b91ce22016-06-20 18:26:15 +0200570 printf("Testing subscriber GSUP handling\n");
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100571
572 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
573
574 /* Check for emptiness */
575 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
576
577 /* Allocate entry 1 */
578 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100579 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100580 s1found = gprs_subscr_get_by_imsi(imsi1);
581 OSMO_ASSERT(s1found == s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100582 gprs_subscr_put(s1found);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100583
584 /* Create a context */
585 OSMO_ASSERT(count(gprs_llme_list()) == 0);
586 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100587
588 /* Attach s1 to ctx */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100589 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100590 ctx->subscr->sgsn_data->mm = ctx;
591
592 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100593 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100594 OSMO_ASSERT(rc >= 0);
595 OSMO_ASSERT(last_updated_subscr == s1);
596
597 /* Check triplets */
598 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
599 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
600 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
601
602 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100603 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100604 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100605 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100606 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100607
608 /* Check triplets */
609 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
610 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
611 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
612
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100613 /* Inject UpdateLocRes GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100614 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100615 OSMO_ASSERT(rc >= 0);
616 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100617 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100618 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400619 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
620 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100621 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
622 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
623 struct sgsn_subscriber_pdp_data, list);
624 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
625 pdpd = llist_entry(pdpd->list.next,
626 struct sgsn_subscriber_pdp_data, list);
627 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100628
629 /* Check authorization */
630 OSMO_ASSERT(s1->authorized == 1);
631
632 /* Inject UpdateLocErr GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100633 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100634 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100635 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100636 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100637
638 /* Check authorization */
639 OSMO_ASSERT(s1->authorized == 0);
640
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100641 /* Inject InsertSubscrData GSUP message */
642 last_updated_subscr = NULL;
643 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Harald Weltee7e3f272016-11-26 14:58:36 +0100644 OSMO_ASSERT(rc == -ENOTSUP); /* not connected */
Harald Welted3356e72016-05-06 13:46:21 +0200645 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100646
647 /* Inject DeleteSubscrData GSUP message */
648 last_updated_subscr = NULL;
649 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
Maxe405f152017-02-15 11:43:59 +0100650 if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
651 printf("Unexpected response to DSD: %d\n", rc);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100652 OSMO_ASSERT(last_updated_subscr == NULL);
653
Jacob Erlbeck00b8b912015-01-08 15:29:01 +0100654 /* Inject wrong LocCancelReq GSUP message */
655 last_updated_subscr = NULL;
656 rc = rx_gsup_message(location_cancellation_req_other,
657 sizeof(location_cancellation_req_other));
658 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
659 OSMO_ASSERT(last_updated_subscr == NULL);
660
661 /* Check cancellation result */
662 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
663 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
664
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100665 /* Inject LocCancelReq GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100666 rc = rx_gsup_message(location_cancellation_req,
667 sizeof(location_cancellation_req));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100668 OSMO_ASSERT(rc >= 0);
669 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100670 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100671
672 /* Check cancellation result */
673 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
674 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
675
Jacob Erlbecke7fea452015-04-07 17:49:48 +0200676 /* Inject LocCancelReq(withdraw) GSUP message */
677 rc = rx_gsup_message(location_cancellation_req_withdraw,
678 sizeof(location_cancellation_req_withdraw));
679 OSMO_ASSERT(rc >= 0);
680 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
681
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100682 /* Inject PurgeMsRes GSUP message */
683 rc = rx_gsup_message(purge_ms_res,
684 sizeof(purge_ms_res));
685 OSMO_ASSERT(rc >= 0);
686 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
687
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100688 /* Free MM context and subscriber */
Jacob Erlbeck265e7352015-01-30 11:57:25 +0100689 OSMO_ASSERT(ctx->subscr == NULL);
690 sgsn_mm_ctx_cleanup_free(ctx);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100691 gprs_subscr_put(s1);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100692 s1found = gprs_subscr_get_by_imsi(imsi1);
693 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100694
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100695 /* Inject PurgeMsRes GSUP message */
696 rc = rx_gsup_message(purge_ms_res,
697 sizeof(purge_ms_res));
698 OSMO_ASSERT(rc >= 0);
699
700 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
701 rc = rx_gsup_message(purge_ms_err,
702 sizeof(purge_ms_err));
703 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
704
Jacob Erlbeck9ca3ace2015-01-29 14:17:51 +0100705 /* Inject PurgeMsErr() GSUP message */
706 rc = rx_gsup_message(purge_ms_err_no_cause,
707 sizeof(purge_ms_err_no_cause));
708 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
709
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100710 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
711 last_updated_subscr = NULL;
712 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck629dacc2015-01-15 17:50:16 +0100713 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100714 OSMO_ASSERT(last_updated_subscr == NULL);
715
716 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
717 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
718 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
719 OSMO_ASSERT(last_updated_subscr == NULL);
720
721 /* Inject LocCancelReq GSUP message (unknown IMSI) */
722 rc = rx_gsup_message(location_cancellation_req,
723 sizeof(location_cancellation_req));
724 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
725 OSMO_ASSERT(last_updated_subscr == NULL);
726
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100727 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200728
729 cleanup_test();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100730}
731
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +0100732int my_gsup_client_send_dummy(struct gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckfdf8ce52015-01-08 16:23:25 +0100733{
734 msgb_free(msg);
735 return 0;
736};
737
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200738/*
739 * Test that a GMM Detach will remove the MMCTX and the
740 * associated LLME.
741 */
742static void test_gmm_detach(void)
743{
744 struct gprs_ra_id raid = { 0, };
745 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200746 uint32_t local_tlli;
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200747
748 printf("Testing GMM detach\n");
749
750 /* DTAP - Detach Request (MO) */
751 /* normal detach, power_off = 0 */
752 static const unsigned char detach_req[] = {
753 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
754 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
755 };
756
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200757 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200758
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100759 /* Create a context */
760 OSMO_ASSERT(count(gprs_llme_list()) == 0);
761 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200762
763 /* inject the detach */
Harald Weltec28dc2f2015-12-25 19:12:21 +0100764 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100765 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200766
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100767 /* verify that a single message (hopefully the Detach Accept) has been
768 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100769 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100770
771 /* verify that things are gone */
772 OSMO_ASSERT(count(gprs_llme_list()) == 0);
773 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
774 OSMO_ASSERT(!ictx);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200775
776 cleanup_test();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100777}
778
779/*
780 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
781 * will not sent a Detach Accept message (power_off = 1)
782 */
783static void test_gmm_detach_power_off(void)
784{
785 struct gprs_ra_id raid = { 0, };
786 struct sgsn_mm_ctx *ctx, *ictx;
787 uint32_t local_tlli;
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100788
789 printf("Testing GMM detach (power off)\n");
790
791 /* DTAP - Detach Request (MO) */
792 /* normal detach, power_off = 1 */
793 static const unsigned char detach_req[] = {
794 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
795 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
796 };
797
798 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
799
800 /* Create a context */
801 OSMO_ASSERT(count(gprs_llme_list()) == 0);
802 ctx = alloc_mm_ctx(local_tlli, &raid);
803
804 /* inject the detach */
Harald Weltec28dc2f2015-12-25 19:12:21 +0100805 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100806 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100807
808 /* verify that no message (and therefore no Detach Accept) has been
809 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100810 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100811
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200812 /* verify that things are gone */
813 OSMO_ASSERT(count(gprs_llme_list()) == 0);
814 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck12396bd2014-09-30 13:51:45 +0200815 OSMO_ASSERT(!ictx);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200816
817 cleanup_test();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200818}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200819
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200820/*
821 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
822 */
823static void test_gmm_detach_no_mmctx(void)
824{
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100825 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200826 struct gprs_llc_lle *lle;
827 uint32_t local_tlli;
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200828
829 printf("Testing GMM detach (no MMCTX)\n");
830
831 /* DTAP - Detach Request (MO) */
832 /* normal detach, power_off = 0 */
833 static const unsigned char detach_req[] = {
834 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
835 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
836 };
837
838 /* Create an LLME */
839 OSMO_ASSERT(count(gprs_llme_list()) == 0);
840 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
841 lle = gprs_lle_get_or_create(local_tlli, 3);
842
843 OSMO_ASSERT(count(gprs_llme_list()) == 1);
844
845 /* inject the detach */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100846 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100847 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200848
849 /* verify that the LLME is gone */
850 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200851
852 cleanup_test();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200853}
854
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100855/*
Jacob Erlbeck021a0d12014-11-24 15:04:15 +0100856 * Test that a single GMM Detach Accept message will not cause the SGSN to send
857 * any message or leave an MM context at the SGSN.
858 */
859static void test_gmm_detach_accept_unexpected(void)
860{
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100861 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck021a0d12014-11-24 15:04:15 +0100862 struct gprs_llc_lle *lle;
863 uint32_t local_tlli;
864
865 printf("Testing GMM detach accept (unexpected)\n");
866
867 /* DTAP - Detach Accept (MT) */
868 /* normal detach */
869 static const unsigned char detach_acc[] = {
870 0x08, 0x06
871 };
872
873 /* Create an LLME */
874 OSMO_ASSERT(count(gprs_llme_list()) == 0);
875 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
876 lle = gprs_lle_get_or_create(local_tlli, 3);
877
878 /* inject the detach */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100879 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck021a0d12014-11-24 15:04:15 +0100880 detach_acc, ARRAY_SIZE(detach_acc));
881
882 /* verify that no message (and therefore no Status or XID reset) has been
883 * sent by the SGSN */
884 OSMO_ASSERT(sgsn_tx_counter == 0);
885
886 /* verify that things are gone */
887 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200888
889 cleanup_test();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +0100890}
891
892/*
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100893 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
894 */
895static void test_gmm_status_no_mmctx(void)
896{
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100897 struct gprs_ra_id raid = { 0, };
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100898 struct gprs_llc_lle *lle;
899 uint32_t local_tlli;
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100900
901 printf("Testing GMM Status (no MMCTX)\n");
902
903 /* DTAP - GMM Status, protocol error */
904 static const unsigned char gmm_status[] = {
905 0x08, 0x20, 0x6f
906 };
907
908 /* Create an LLME */
909 OSMO_ASSERT(count(gprs_llme_list()) == 0);
910 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
911 lle = gprs_lle_get_or_create(local_tlli, 3);
912
913 OSMO_ASSERT(count(gprs_llme_list()) == 1);
914
915 /* inject the detach */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100916 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100917 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100918
919 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100920 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100921
922 /* verify that the LLME is gone */
923 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200924
925 cleanup_test();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100926}
927
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100928int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
929{
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100930 int rc;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100931 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100932 if (rc == -ENOTSUP) {
933 OSMO_ASSERT(mmctx->subscr);
934 gprs_subscr_update(mmctx->subscr);
935 }
936 return rc;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100937}
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100938
Pau Espin Pedrold17d6212018-01-07 18:05:22 +0100939int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
940 const uint8_t *auts_rand)
941{
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100942 gprs_subscr_update(mmctx->subscr);
943 return 0;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100944}
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100945
Pau Espin Pedrold17d6212018-01-07 18:05:22 +0100946int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
947 const uint8_t *auts_rand)
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100948{
949 /* Fake an authentication */
950 OSMO_ASSERT(mmctx->subscr);
Neels Hofmeyr4a8d5012018-04-22 19:29:41 +0200951 mmctx->sec_ctx = OSMO_AUTH_TYPE_GSM;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100952 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100953
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100954 return 0;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100955}
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100956
Pau Espin Pedrol78a62a52017-08-16 11:30:01 +0200957int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand)
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100958{
959 struct gsm_auth_tuple at = {
Harald Welte34ef4c52016-04-20 13:13:19 +0200960 .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
Neels Hofmeyr4eec3df2017-02-24 06:24:45 +0100961 .vec.auth_types = OSMO_AUTH_TYPE_GSM,
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100962 .key_seq = 0
963 };
964
965 /* Fake an authentication */
966 OSMO_ASSERT(mmctx->subscr);
967 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
968
969 gprs_subscr_update_auth_info(mmctx->subscr);
970
971 return 0;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100972}
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100973
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100974#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
975 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
976
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100977static int auth_info_skip = 0;
978static int upd_loc_skip = 0;
979
Pau Espin Pedrold17d6212018-01-07 18:05:22 +0100980int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
981 const uint8_t *auts_rand)
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100982{
983 static const uint8_t send_auth_info_res[] = {
984 0x0a,
985 TEST_GSUP_IMSI_LONG_IE,
986 0x03, 0x22, /* Auth tuple */
987 0x20, 0x10,
988 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
989 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
990 0x21, 0x04,
991 0x51, 0xe5, 0x51, 0xe5,
992 0x22, 0x08,
993 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
994 };
995
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100996 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100997
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100998 if (auth_info_skip > 0) {
999 auth_info_skip -= 1;
1000 return -EAGAIN;
1001 }
1002
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001003 /* Fake an SendAuthInfoRes */
1004 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1005
1006 return 0;
1007};
1008
1009int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1010 static const uint8_t update_location_res[] = {
1011 0x06,
1012 TEST_GSUP_IMSI_LONG_IE,
1013 0x04, 0x00, /* PDP info complete */
1014 0x05, 0x12,
1015 0x10, 0x01, 0x01,
1016 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1017 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +02001018 0x08, 0x07, /* MSISDN 49166213323 encoded */
1019 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freytherfe4a9f62015-05-17 20:58:40 +02001020 0x09, 0x07, /* MSISDN 38166213323 encoded */
1021 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001022 };
1023
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001024 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001025
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001026 if (upd_loc_skip > 0) {
1027 upd_loc_skip -= 1;
1028 return -EAGAIN;
1029 }
1030
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001031 /* Fake an UpdateLocRes */
1032 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1033};
1034
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +01001035int my_gsup_client_send(struct gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001036{
Harald Welte4e349d62016-04-25 19:07:34 +02001037 struct osmo_gsup_message to_peer = {0};
1038 struct osmo_gsup_message from_peer = {0};
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001039 struct msgb *reply_msg;
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001040 int rc;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001041
1042 /* Simulate the GSUP peer */
Harald Welte4e349d62016-04-25 19:07:34 +02001043 rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001044 OSMO_ASSERT(rc >= 0);
1045 OSMO_ASSERT(to_peer.imsi[0] != 0);
Neels Hofmeyr64a40bf2017-01-13 03:10:54 +01001046 osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001047
1048 /* This invalidates the pointers in to_peer */
1049 msgb_free(msg);
1050
1051 switch (to_peer.message_type) {
Harald Welte4e349d62016-04-25 19:07:34 +02001052 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001053 /* Send UPDATE_LOCATION_RESULT */
1054 return my_subscr_request_update_gsup_auth(NULL);
1055
Harald Welte4e349d62016-04-25 19:07:34 +02001056 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001057 /* Send SEND_AUTH_INFO_RESULT */
Pau Espin Pedrold17d6212018-01-07 18:05:22 +01001058 return my_subscr_request_auth_info_gsup_auth(NULL, NULL, NULL);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001059
Harald Welte4e349d62016-04-25 19:07:34 +02001060 case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
1061 from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001062 break;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001063
1064 default:
1065 if ((to_peer.message_type & 0b00000011) == 0) {
1066 /* Unhandled request */
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001067 /* Send error(NOT_IMPL) */
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001068 from_peer.message_type = to_peer.message_type + 1;
1069 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1070 break;
1071 }
1072
1073 /* Ignore it */
1074 return 0;
1075 }
1076
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +01001077 reply_msg = gsup_client_msgb_alloc();
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001078 reply_msg->l2h = reply_msg->data;
Harald Welte4e349d62016-04-25 19:07:34 +02001079 osmo_gsup_encode(reply_msg, &from_peer);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001080 gprs_subscr_rx_gsup_message(reply_msg);
1081 msgb_free(reply_msg);
1082
1083 return 0;
1084};
1085
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001086/*
1087 * Test the GMM Rejects
1088 */
1089static void test_gmm_reject(void)
1090{
1091 struct gprs_ra_id raid = { 0, };
1092 struct sgsn_mm_ctx *ctx = NULL;
1093 uint32_t foreign_tlli;
1094 struct gprs_llc_lle *lle;
1095 int idx;
1096
1097 /* DTAP - Attach Request */
1098 /* Invalid MI length */
1099 static const unsigned char attach_req_inv_mi_len[] = {
1100 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1101 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1102 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1103 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1104 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1105 };
1106
1107 /* DTAP - Attach Request */
1108 /* Invalid MI type (IMEI) */
1109 static const unsigned char attach_req_inv_mi_type[] = {
1110 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1111 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1112 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1113 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1114 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1115 };
1116
1117 /* DTAP - Routing Area Update Request */
1118 static const unsigned char dtap_ra_upd_req[] = {
1119 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1120 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1121 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1122 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1123 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1124 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1125 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1126 };
1127
1128 /* DTAP - Routing Area Update Request */
1129 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1130 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1131 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1132 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1133 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1134 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1135 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1136 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1137 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1138 };
1139
1140 /* DTAP - Routing Area Update Request */
1141 /* Invalid cap length */
1142 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1143 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1144 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1147 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1148 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1149 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1150 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1151 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1152 };
1153
1154 struct test {
1155 const char *title;
1156 const unsigned char *msg;
1157 unsigned msg_len;
1158 unsigned num_resp;
1159
1160 };
1161 static struct test tests[] = {
1162 {
1163 .title = "Attach Request (invalid MI length)",
1164 .msg = attach_req_inv_mi_len,
1165 .msg_len = sizeof(attach_req_inv_mi_len),
1166 .num_resp = 1 /* Reject */
1167
1168 },
1169 {
1170 .title = "Attach Request (invalid MI type)",
1171 .msg = attach_req_inv_mi_type,
1172 .msg_len = sizeof(attach_req_inv_mi_type),
1173 .num_resp = 1 /* Reject */
1174 },
1175 {
1176 .title = "Routing Area Update Request (valid)",
1177 .msg = dtap_ra_upd_req,
1178 .msg_len = sizeof(dtap_ra_upd_req),
1179 .num_resp = 2 /* XID Reset + Reject */
1180 },
1181 {
1182 .title = "Routing Area Update Request (invalid type)",
1183 .msg = dtap_ra_upd_req_inv_type,
1184 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1185 .num_resp = 1 /* Reject */
1186 },
1187 {
1188 .title = "Routing Area Update Request (invalid CAP length)",
1189 .msg = dtap_ra_upd_req_inv_cap_len,
1190 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1191 .num_resp = 1 /* Reject */
1192 },
1193 };
1194
1195 printf("Testing GMM reject\n");
1196
1197 /* reset the PRNG used by sgsn_alloc_ptmsi */
1198 srand(1);
1199
1200 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1201
1202 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1203
1204 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1205 const struct test *test = &tests[idx];
1206 printf(" - %s\n", test->title);
1207
1208 /* Create a LLE/LLME */
1209 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1210 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1211
1212 /* Inject the Request message */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +01001213 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001214 test->msg, test->msg_len);
1215
1216 /* We expect a Reject message */
1217 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1218 sgsn_tx_counter, test->num_resp);
1219 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1220
1221 /* verify that LLME/MM are removed */
1222 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1223 OSMO_ASSERT(ctx == NULL);
1224 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1225 }
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001226
1227 cleanup_test();
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001228}
1229
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001230/*
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001231 * Test cancellation of attached MM contexts
1232 */
1233static void test_gmm_cancel(void)
1234{
1235 struct gprs_ra_id raid = { 0, };
1236 struct sgsn_mm_ctx *ctx = NULL;
1237 struct sgsn_mm_ctx *ictx;
1238 uint32_t ptmsi1;
1239 uint32_t foreign_tlli;
1240 uint32_t local_tlli = 0;
1241 struct gprs_llc_lle *lle;
1242 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1243
1244 /* DTAP - Attach Request */
1245 /* The P-TMSI is not known by the SGSN */
1246 static const unsigned char attach_req[] = {
1247 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1248 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1249 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1250 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1251 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1252 };
1253
1254 /* DTAP - Identity Response IMEI */
1255 static const unsigned char ident_resp_imei[] = {
1256 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1257 0x56
1258 };
1259
1260 /* DTAP - Identity Response IMSI */
1261 static const unsigned char ident_resp_imsi[] = {
1262 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1263 0x54
1264 };
1265
1266 /* DTAP - Attach Complete */
1267 static const unsigned char attach_compl[] = {
1268 0x08, 0x03
1269 };
1270
1271 printf("Testing cancellation\n");
1272
1273 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1274
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001275 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1276
1277 /* Create a LLE/LLME */
1278 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1279 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1280 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1281
1282 /* inject the attach request */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +01001283 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001284 attach_req, ARRAY_SIZE(attach_req));
1285
1286 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1287 OSMO_ASSERT(ctx != NULL);
Alexander Couzens5e33f442017-01-31 15:34:26 +01001288 OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001289
1290 /* we expect an identity request (IMEI) */
1291 OSMO_ASSERT(sgsn_tx_counter == 1);
1292
1293 /* inject the identity response (IMEI) */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001294 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001295 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1296
1297 /* we expect an identity request (IMSI) */
1298 OSMO_ASSERT(sgsn_tx_counter == 1);
1299
1300 /* inject the identity response (IMSI) */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001301 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001302 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1303
1304 /* check that the MM context has not been removed due to a failed
1305 * authorization */
1306 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1307
Alexander Couzens5e33f442017-01-31 15:34:26 +01001308 OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001309
1310 /* we expect an attach accept/reject */
1311 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck28c28f92015-10-12 19:36:32 +02001312 ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
1313 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001314
1315 /* this has been randomly assigned by the SGSN */
1316 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1317
1318 /* inject the attach complete */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001319 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001320 attach_compl, ARRAY_SIZE(attach_compl));
1321
Alexander Couzens5e33f442017-01-31 15:34:26 +01001322 OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001323
1324 /* we don't expect a response */
1325 OSMO_ASSERT(sgsn_tx_counter == 0);
1326
1327 /* cancel */
Jacob Erlbeck41010082015-01-05 17:51:17 +01001328 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001329
1330 /* verify that things are gone */
1331 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1332 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1333 OSMO_ASSERT(!ictx);
1334
1335 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001336
1337 cleanup_test();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001338}
1339
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001340static void test_apn_matching(void)
1341{
1342 struct apn_ctx *actx, *actxs[9];
1343
1344 printf("Testing APN matching\n");
1345
1346 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1347 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1348 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1349 actxs[3] = NULL;
1350
1351 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1352 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1353 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1354 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1355
1356 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1357
1358 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1359 OSMO_ASSERT(actx == actxs[2]);
1360 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1361 OSMO_ASSERT(actx == actxs[2]);
1362 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1363 OSMO_ASSERT(actx == actxs[1]);
1364 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1365 OSMO_ASSERT(actx == actxs[1]);
1366 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1367 OSMO_ASSERT(actx == actxs[0]);
1368 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1369 OSMO_ASSERT(actx == NULL);
1370
1371 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1372 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1373 OSMO_ASSERT(actx == actxs[3]);
1374
1375 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1376 OSMO_ASSERT(actx == actxs[4]);
1377
1378 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1379 OSMO_ASSERT(actx == actxs[6]);
1380
1381 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1382 OSMO_ASSERT(actx == actxs[5]);
1383
1384 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1385 OSMO_ASSERT(actx == actxs[7]);
1386
1387 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1388 OSMO_ASSERT(actx == actxs[8]);
1389
1390 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1391 OSMO_ASSERT(actx == actxs[7]);
1392
1393 /* Free APN contexts and check how the matching changes */
1394
1395 sgsn_apn_ctx_free(actxs[7]);
1396 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1397 OSMO_ASSERT(actx == actxs[8]);
1398
1399 sgsn_apn_ctx_free(actxs[8]);
1400 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1401 OSMO_ASSERT(actx == actxs[6]);
1402
1403 sgsn_apn_ctx_free(actxs[6]);
1404 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1405 OSMO_ASSERT(actx == actxs[1]);
1406
1407 sgsn_apn_ctx_free(actxs[5]);
1408 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1409 OSMO_ASSERT(actx == actxs[4]);
1410
1411 sgsn_apn_ctx_free(actxs[4]);
1412 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1413 OSMO_ASSERT(actx == actxs[2]);
1414
1415 sgsn_apn_ctx_free(actxs[2]);
1416 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1417 OSMO_ASSERT(actx == actxs[1]);
1418
1419 sgsn_apn_ctx_free(actxs[1]);
1420 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1421 OSMO_ASSERT(actx == actxs[0]);
1422
1423 sgsn_apn_ctx_free(actxs[0]);
1424 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1425 OSMO_ASSERT(actx == actxs[3]);
1426
1427 sgsn_apn_ctx_free(actxs[3]);
1428 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1429 OSMO_ASSERT(actx == NULL);
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001430
1431 cleanup_test();
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001432}
1433
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001434struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1435 struct sgsn_subscriber_data *sdata);
1436
1437static void test_ggsn_selection(void)
1438{
1439 struct apn_ctx *actxs[4];
1440 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
Neels Hofmeyre2c94d62017-01-10 00:49:56 +01001441 struct gprs_subscr *s1;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001442 const char *imsi1 = "1234567890";
1443 struct sgsn_mm_ctx *ctx;
1444 struct gprs_ra_id raid = { 0, };
1445 uint32_t local_tlli = 0xffeeddcc;
1446 enum gsm48_gsm_cause gsm_cause;
1447 struct tlv_parsed tp;
1448 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1449 struct sgsn_subscriber_pdp_data *pdp_data;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001450 char apn_str[GSM_APN_LENGTH];
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001451
1452 printf("Testing GGSN selection\n");
1453
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +01001454 gsup_client_send_cb = my_gsup_client_send_dummy;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001455
1456 /* Check for emptiness */
1457 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1458
1459 /* Create a context */
1460 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1461 ctx = alloc_mm_ctx(local_tlli, &raid);
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001462 osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001463
1464 /* Allocate and attach a subscriber */
1465 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1466 assert_subscr(s1, imsi1);
1467
1468 tp.lv[GSM48_IE_GSM_APN].len = 0;
1469 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1470
1471 /* TODO: Add PDP info entries to s1 */
1472
1473 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1474 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1475 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1476
1477 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1478 actxs[0]->ggsn = ggcs[0];
1479 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1480 actxs[1]->ggsn = ggcs[1];
1481 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1482 actxs[2]->ggsn = ggcs[2];
1483
Holger Hans Peter Freytherab9422e2015-05-24 20:51:17 +08001484 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1485 pdp_data->context_id = 1;
1486 pdp_data->pdp_type = 0x0121;
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001487 osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
Holger Hans Peter Freytherab9422e2015-05-24 20:51:17 +08001488
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001489 /* Resolve GGSNs */
1490
1491 tp.lv[GSM48_IE_GSM_APN].len =
1492 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1493
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001494 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001495 OSMO_ASSERT(ggc != NULL);
1496 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001497 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001498
1499 tp.lv[GSM48_IE_GSM_APN].len =
1500 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1501
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001502 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001503 OSMO_ASSERT(ggc != NULL);
1504 OSMO_ASSERT(ggc->id == 1);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001505 OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001506
1507 tp.lv[GSM48_IE_GSM_APN].len = 0;
1508 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1509
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001510 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001511 OSMO_ASSERT(ggc != NULL);
1512 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001513 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001514
1515 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1516 actxs[3]->ggsn = ggcs[2];
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001517 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001518 OSMO_ASSERT(ggc != NULL);
1519 OSMO_ASSERT(ggc->id == 2);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001520 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001521
1522 sgsn_apn_ctx_free(actxs[3]);
1523 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1524
1525 tp.lv[GSM48_IE_GSM_APN].len =
1526 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1527
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001528 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001529 OSMO_ASSERT(ggc == NULL);
1530 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001531 OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001532
1533 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001534 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001535 OSMO_ASSERT(ggc == NULL);
1536 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1537
1538 /* Add PDP data entry to subscriber */
1539
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001540 osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001541
1542 tp.lv[GSM48_IE_GSM_APN].len =
1543 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1544
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001545 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001546 OSMO_ASSERT(ggc != NULL);
1547 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001548 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001549
1550 tp.lv[GSM48_IE_GSM_APN].len =
1551 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1552
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001553 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001554 OSMO_ASSERT(ggc == NULL);
1555 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001556 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001557
1558 /* Cleanup */
1559
Neels Hofmeyre2c94d62017-01-10 00:49:56 +01001560 gprs_subscr_put(s1);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001561 sgsn_mm_ctx_cleanup_free(ctx);
1562
1563 assert_no_subscrs();
1564
1565 sgsn_apn_ctx_free(actxs[0]);
1566 sgsn_apn_ctx_free(actxs[1]);
1567 sgsn_apn_ctx_free(actxs[2]);
1568
1569 sgsn_ggsn_ctx_free(ggcs[0]);
1570 sgsn_ggsn_ctx_free(ggcs[1]);
1571 sgsn_ggsn_ctx_free(ggcs[2]);
1572
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +01001573 gsup_client_send_cb = __real_gsup_client_send;
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001574
1575 cleanup_test();
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001576}
1577
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001578static struct log_info_cat gprs_categories[] = {
1579 [DMM] = {
1580 .name = "DMM",
1581 .description = "Layer3 Mobility Management (MM)",
1582 .color = "\033[1;33m",
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001583 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001584 },
1585 [DPAG] = {
1586 .name = "DPAG",
1587 .description = "Paging Subsystem",
1588 .color = "\033[1;38m",
1589 .enabled = 1, .loglevel = LOGL_NOTICE,
1590 },
1591 [DMEAS] = {
1592 .name = "DMEAS",
1593 .description = "Radio Measurement Processing",
1594 .enabled = 0, .loglevel = LOGL_NOTICE,
1595 },
1596 [DREF] = {
1597 .name = "DREF",
1598 .description = "Reference Counting",
1599 .enabled = 0, .loglevel = LOGL_NOTICE,
1600 },
1601 [DGPRS] = {
1602 .name = "DGPRS",
1603 .description = "GPRS Packet Service",
1604 .enabled = 1, .loglevel = LOGL_DEBUG,
1605 },
1606 [DNS] = {
1607 .name = "DNS",
1608 .description = "GPRS Network Service (NS)",
1609 .enabled = 1, .loglevel = LOGL_INFO,
1610 },
1611 [DBSSGP] = {
1612 .name = "DBSSGP",
1613 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1614 .enabled = 1, .loglevel = LOGL_DEBUG,
1615 },
1616 [DLLC] = {
1617 .name = "DLLC",
1618 .description = "GPRS Logical Link Control Protocol (LLC)",
1619 .enabled = 1, .loglevel = LOGL_DEBUG,
1620 },
1621 [DSNDCP] = {
1622 .name = "DSNDCP",
1623 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1624 .enabled = 1, .loglevel = LOGL_DEBUG,
1625 },
1626};
1627
1628static struct log_info info = {
1629 .cat = gprs_categories,
1630 .num_cat = ARRAY_SIZE(gprs_categories),
1631};
1632
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001633int main(int argc, char **argv)
1634{
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001635 void *osmo_sgsn_ctx;
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001636 void *msgb_ctx;
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001637
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001638 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
Neels Hofmeyr8de6b862018-04-16 00:57:10 +02001639 osmo_init_logging2(osmo_sgsn_ctx, &info);
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001640 tall_bsc_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "bsc");
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001641 msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001642
Alexander Couzens32fdba02016-07-05 09:52:52 +02001643 sgsn_rate_ctr_init();
Jacob Erlbeckb2acd742014-11-13 10:48:39 +01001644 sgsn_auth_init();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001645 gprs_subscr_init(sgsn);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001646
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001647 test_llme();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001648 test_subscriber();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +01001649 test_auth_triplets();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +01001650 test_subscriber_gsup();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +02001651 test_gmm_detach();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +01001652 test_gmm_detach_power_off();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001653 test_gmm_detach_no_mmctx();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +01001654 test_gmm_detach_accept_unexpected();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001655 test_gmm_status_no_mmctx();
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001656 test_gmm_reject();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001657 test_gmm_cancel();
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001658 test_apn_matching();
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001659 test_ggsn_selection();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001660 printf("Done\n");
Jacob Erlbeck80dbcf12015-01-13 11:46:32 +01001661
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001662 talloc_report_full(osmo_sgsn_ctx, stderr);
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001663 OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
Alexander Couzens32fdba02016-07-05 09:52:52 +02001664 OSMO_ASSERT(talloc_total_blocks(tall_bsc_ctx) == 2);
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001665 return 0;
1666}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001667
1668
1669/* stubs */
1670struct osmo_prim_hdr;
1671int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1672{
1673 abort();
1674}