blob: 91a3dcf568209b2a740b20974a7c952807e794b4 [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
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +010022#include <osmocom/core/application.h>
23#include <osmocom/core/msgb.h>
24#include <osmocom/core/rate_ctr.h>
25#include <osmocom/core/utils.h>
26#include <osmocom/gsm/apn.h>
27#include <osmocom/gsm/gsm_utils.h>
28#include <osmocom/gsm/gsup.h>
29#include <osmocom/gprs/gprs_bssgp.h>
30#include <osmocom/vty/vty.h>
31
32#include <osmocom/gsupclient/gsup_client.h>
33
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020034#include <osmocom/sgsn/gprs_llc.h>
35#include <osmocom/sgsn/sgsn.h>
36#include <osmocom/sgsn/gprs_gmm.h>
37#include <osmocom/sgsn/debug.h>
38#include <osmocom/sgsn/gprs_subscriber.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020039#include <osmocom/sgsn/gprs_utils.h>
Pau Espin Pedrol31c46572019-09-02 16:45:27 +020040#include <osmocom/sgsn/gprs_gmm_fsm.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020041
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020042#include <stdio.h>
43
Pau Espin Pedrol749ca7c2022-12-22 19:49:37 +010044#include "gprs_gb_parse.h"
45
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010046void *tall_sgsn_ctx;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020047static struct sgsn_instance sgsn_inst = {
48 .config_file = "osmo_sgsn.cfg",
49 .cfg = {
50 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010051 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Neels Hofmeyr340a7e92022-03-07 15:37:24 +010052 .gea_encryption_mask = 0x1,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020053 },
54};
55struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010056unsigned sgsn_tx_counter = 0;
Jacob Erlbeck133e8622015-10-12 19:36:32 +020057struct msgb *last_msg = NULL;
58struct gprs_gb_parse_context last_dl_parse_ctx;
59
60static void reset_last_msg()
61{
62 if (last_msg)
63 msgb_free(last_msg);
64
65 last_msg = NULL;
66 memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
67}
Jacob Erlbeck189999d2014-10-27 14:34:13 +010068
Jacob Erlbeckcf151872015-10-12 19:36:31 +020069static void cleanup_test()
70{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020071 reset_last_msg();
72}
73
74static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
75{
76 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
77
78 if (parse_ctx->new_ptmsi_enc)
79 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
80
81 return new_ptmsi;
Jacob Erlbeckcf151872015-10-12 19:36:31 +020082}
83
Jacob Erlbeck189999d2014-10-27 14:34:13 +010084/* override */
85int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
86 struct bssgp_dl_ud_par *dup)
87{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020088 int rc;
89
90 reset_last_msg();
91
92 last_msg = msg;
93 OSMO_ASSERT(msgb_data(last_msg) != NULL);
94
95 rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
96 &last_dl_parse_ctx);
97
98 fprintf(stderr, "Got DL LLC message: %s\n",
99 gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
100
101 OSMO_ASSERT(rc > 0);
102
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100103 sgsn_tx_counter += 1;
104 return 0;
105}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200106
Max3b6332f2017-11-01 13:28:38 +0100107/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
108int __real_osmo_get_rand_id(uint8_t *data, size_t len);
109int mock_osmo_get_rand_id(uint8_t *data, size_t len);
110int (*osmo_get_rand_id_cb)(uint8_t *, size_t) =
111 &mock_osmo_get_rand_id;
Max4011e722016-07-05 15:19:12 +0200112
Max3b6332f2017-11-01 13:28:38 +0100113int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200114{
Max3b6332f2017-11-01 13:28:38 +0100115 return (*osmo_get_rand_id_cb)(buf, num);
Max4011e722016-07-05 15:19:12 +0200116}
117/* make results of A&C ref predictable */
Max3b6332f2017-11-01 13:28:38 +0100118int mock_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200119{
120 if (num > 1)
Max3b6332f2017-11-01 13:28:38 +0100121 return __real_osmo_get_rand_id(buf, num);
Max4011e722016-07-05 15:19:12 +0200122 buf[0] = 0;
123 return 1;
124}
125
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100126/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100127void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
128void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100129 &__real_sgsn_update_subscriber_data;
130
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100131void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100132{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100133 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100134}
135
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100136/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
137int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
138int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
139 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100140
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100141int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
142 return (*subscr_request_update_location_cb)(mmctx);
143};
144
145/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200146int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
147int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) =
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100148 &__real_gprs_subscr_request_auth_info;
149
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200150int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
151 return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100152};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100153
Neels Hofmeyr814fef02016-12-08 21:19:57 +0100154/* override, requires '-Wl,--wrap=gsup_client_send' */
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200155int __real_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
156int (*osmo_gsup_client_send_cb)(struct osmo_gsup_client *gsupc, struct msgb *msg) =
157 &__real_osmo_gsup_client_send;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100158
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200159int __wrap_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100160{
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200161 return (*osmo_gsup_client_send_cb)(gsupc, msg);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100162};
163
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200164static int count(struct llist_head *head)
165{
166 struct llist_head *cur;
167 int count = 0;
168
169 llist_for_each(cur, head)
170 count += 1;
171
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100172 return count;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200173}
174
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200175static struct msgb *create_msg(const uint8_t *data, size_t len)
176{
177 struct msgb *msg = msgb_alloc(len + 8, "test message");
178 msg->l1h = msgb_put(msg, 8);
179 msg->l2h = msgb_put(msg, len);
180 memcpy(msg->l2h, data, len);
181
182 msgb_bcid(msg) = msg->l1h;
183 msgb_gmmh(msg) = msg->l2h;
184 return msg;
185}
186
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100187/*
188 * Create a context and search for it
189 */
190static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
191{
192 struct sgsn_mm_ctx *ctx, *ictx;
193 struct gprs_llc_lle *lle;
194 int old_count = count(gprs_llme_list());
195
196 lle = gprs_lle_get_or_create(tlli, 3);
Alexander Couzens2b5fb8e2017-02-04 06:01:00 +0100197 ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
Harald Weltef97ee042015-12-25 19:12:21 +0100198 ctx->gb.llme = lle->llme;
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100199
200 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
201 OSMO_ASSERT(ictx == ctx);
202
203 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
204
205 return ctx;
206}
207
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100208static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
Jacob Erlbeck91580892016-01-04 18:43:33 +0100209 const struct gprs_ra_id *bssgp_raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100210 const uint8_t *data, size_t data_len)
211{
212 struct msgb *msg;
213
Jacob Erlbeck133e8622015-10-12 19:36:32 +0200214 reset_last_msg();
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100215 sgsn_tx_counter = 0;
216
217 msg = create_msg(data, data_len);
218 msgb_tlli(msg) = tlli;
Jacob Erlbeck91580892016-01-04 18:43:33 +0100219 bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
Max82040102016-07-06 11:59:18 +0200220 gsm0408_gprs_rcvmsg_gb(msg, llme, false);
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100221 msgb_free(msg);
222}
223
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200224static void test_llme(void)
225{
226 struct gprs_llc_lle *lle, *lle_copy;
227 uint32_t local_tlli;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200228
229 printf("Testing LLME allocations\n");
230 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200231
232 /* initial state */
233 OSMO_ASSERT(count(gprs_llme_list()) == 0);
234
235 /* Create a new entry */
236 lle = gprs_lle_get_or_create(local_tlli, 3);
237 OSMO_ASSERT(lle);
238 OSMO_ASSERT(count(gprs_llme_list()) == 1);
239
240 /* No new entry is created */
241 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
242 OSMO_ASSERT(lle == lle_copy);
243 OSMO_ASSERT(count(gprs_llme_list()) == 1);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200244
245 /* unassign which should delete it*/
Max39550252016-06-28 17:39:20 +0200246 gprs_llgmm_unassign(lle->llme);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200247
248 /* Check that everything was cleaned up */
249 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200250
251 cleanup_test();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200252}
253
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100254struct gprs_subscr *last_updated_subscr = NULL;
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100255void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100256{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100257 OSMO_ASSERT(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100258 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100259 __func__, mmctx, mmctx->subscr);
260 last_updated_subscr = mmctx->subscr;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100261}
262
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100263static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100264{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100265 struct gprs_subscr *sfound;
Jacob Erlbeck6be9ffa2015-01-19 08:57:07 +0100266 OSMO_ASSERT(subscr);
267 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100268
269 sfound = gprs_subscr_get_by_imsi(imsi);
270 OSMO_ASSERT(sfound == subscr);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100271
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100272 gprs_subscr_put(sfound);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100273}
274
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100275static void show_subscrs(FILE *out)
276{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100277 struct gprs_subscr *subscr;
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100278
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100279 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100280 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100281 "use count: %d\n",
282 subscr->imsi, subscr->use_count);
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100283 }
284}
285
286static void assert_no_subscrs()
287{
288 show_subscrs(stdout);
289 fflush(stdout);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100290 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100291}
292
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100293#define VERBOSE_ASSERT(val, expect_op, fmt) \
294 do { \
295 printf(#val " == " fmt "\n", (val)); \
296 OSMO_ASSERT((val) expect_op); \
297 } while (0);
298
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100299static void test_subscriber(void)
300{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100301 struct gprs_subscr *s1, *s2, *s3;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100302 const char *imsi1 = "1234567890";
303 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100304 const char *imsi3 = "5656565656";
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100305
306 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
307
308 printf("Testing core subscriber data API\n");
309
310 /* Check for emptiness */
311 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
312 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100313 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100314 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100315
316 /* Allocate entry 1 */
317 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100318 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
319 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100320 assert_subscr(s1, imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100321 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100322 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100323
324 /* Allocate entry 2 */
325 s2 = gprs_subscr_get_or_create(imsi2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100326 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
327 s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100328
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100329 /* Allocate entry 3 */
330 s3 = gprs_subscr_get_or_create(imsi3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100331 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100332
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100333 /* Check entries */
334 assert_subscr(s1, imsi1);
335 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100336 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100337
338 /* Update entry 1 */
339 last_updated_subscr = NULL;
340 gprs_subscr_update(s1);
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100341 OSMO_ASSERT(last_updated_subscr == NULL);
342 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100343 OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100344
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100345 /* There is no subscriber cache. Verify it */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100346 gprs_subscr_cleanup(s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100347 gprs_subscr_put(s1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100348 s1 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100349 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
350 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100351
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100352 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100353 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100354
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100355 /* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100356 gprs_subscr_cleanup(s2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100357 gprs_subscr_put(s2);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100358 s2 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100359 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100360 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
361 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100362 assert_subscr(s3, imsi3);
363
364 /* Try to delete entry 3 */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100365 gprs_subscr_cleanup(s3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100366 gprs_subscr_put(s3);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100367 s3 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100368 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100369 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100370
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100371 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100372
373 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200374
375 cleanup_test();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100376}
377
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100378static void test_auth_triplets(void)
379{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100380 struct gprs_subscr *s1, *s1found;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100381 const char *imsi1 = "1234567890";
382 struct gsm_auth_tuple *at;
383 struct sgsn_mm_ctx *ctx;
384 struct gprs_ra_id raid = { 0, };
385 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100386
387 printf("Testing authentication triplet handling\n");
388
389 /* Check for emptiness */
390 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
391
392 /* Allocate entry 1 */
393 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100394 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100395 s1found = gprs_subscr_get_by_imsi(imsi1);
396 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100397 gprs_subscr_put(s1found);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100398
399 /* Create a context */
400 OSMO_ASSERT(count(gprs_llme_list()) == 0);
401 ctx = alloc_mm_ctx(local_tlli, &raid);
402
403 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100404 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100405 ctx->subscr->sgsn_data->mm = ctx;
406
407 /* Try to get auth tuple */
408 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
409 OSMO_ASSERT(at == NULL);
410
411 /* Add triplets */
412 s1->sgsn_data->auth_triplets[0].key_seq = 0;
413 s1->sgsn_data->auth_triplets[1].key_seq = 1;
414 s1->sgsn_data->auth_triplets[2].key_seq = 2;
415
416 /* Try to get auth tuple */
417 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
418 OSMO_ASSERT(at != NULL);
419 OSMO_ASSERT(at->key_seq == 0);
420 OSMO_ASSERT(at->use_count == 1);
421 at = sgsn_auth_get_tuple(ctx, at->key_seq);
422 OSMO_ASSERT(at != NULL);
423 OSMO_ASSERT(at->key_seq == 1);
424 OSMO_ASSERT(at->use_count == 1);
425 at = sgsn_auth_get_tuple(ctx, at->key_seq);
426 OSMO_ASSERT(at != NULL);
427 OSMO_ASSERT(at->key_seq == 2);
428 OSMO_ASSERT(at->use_count == 1);
429 at = sgsn_auth_get_tuple(ctx, at->key_seq);
430 OSMO_ASSERT(at == NULL);
431
432 /* Free MM context and subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100433 gprs_subscr_put(s1);
Jacob Erlbecke671d252015-01-26 14:43:07 +0100434 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100435 s1found = gprs_subscr_get_by_imsi(imsi1);
436 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200437
438 cleanup_test();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100439}
440
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100441#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
442
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100443static int rx_gsup_message(const uint8_t *data, size_t data_len)
444{
445 struct msgb *msg;
446 int rc;
447
448 msg = msgb_alloc(1024, __func__);
449 msg->l2h = msgb_put(msg, data_len);
450 OSMO_ASSERT(msg->l2h != NULL);
451 memcpy(msg->l2h, data, data_len);
452 rc = gprs_subscr_rx_gsup_message(msg);
453 msgb_free(msg);
454
455 return rc;
456}
457
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100458static void test_subscriber_gsup(void)
459{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100460 struct gprs_subscr *s1, *s1found;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100461 const char *imsi1 = "1234567890";
462 struct sgsn_mm_ctx *ctx;
463 struct gprs_ra_id raid = { 0, };
464 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100465 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100466 int rc;
467
468 static const uint8_t send_auth_info_res[] = {
469 0x0a,
470 TEST_GSUP_IMSI1_IE,
471 0x03, 0x22, /* Auth tuple */
472 0x20, 0x10,
473 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
474 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
475 0x21, 0x04,
476 0x21, 0x22, 0x23, 0x24,
477 0x22, 0x08,
478 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
479 0x03, 0x22, /* Auth tuple */
480 0x20, 0x10,
481 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
482 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
483 0x21, 0x04,
484 0xa1, 0xa2, 0xa3, 0xa4,
485 0x22, 0x08,
486 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
487 };
488
489 static const uint8_t send_auth_info_err[] = {
490 0x09,
491 TEST_GSUP_IMSI1_IE,
492 0x02, 0x01, 0x07 /* GPRS not allowed */
493 };
494
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400495#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
496
497 static const uint8_t s1_msisdn[] = { MSISDN };
498
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100499 static const uint8_t update_location_res[] = {
500 0x06,
501 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400502 0x08, 0x09, MSISDN,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100503 0x04, 0x00, /* PDP info complete */
504 0x05, 0x12,
505 0x10, 0x01, 0x01,
506 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
507 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
508 0x05, 0x11,
509 0x10, 0x01, 0x02,
510 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
511 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
512 };
513
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400514#undef MSISDN
515
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100516 static const uint8_t update_location_err[] = {
517 0x05,
518 TEST_GSUP_IMSI1_IE,
519 0x02, 0x01, 0x07 /* GPRS not allowed */
520 };
521
522 static const uint8_t location_cancellation_req[] = {
523 0x1c,
524 TEST_GSUP_IMSI1_IE,
525 0x06, 0x01, 0x00,
526 };
527
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200528 static const uint8_t location_cancellation_req_withdraw[] = {
529 0x1c,
530 TEST_GSUP_IMSI1_IE,
531 0x06, 0x01, 0x01,
532 };
533
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100534 static const uint8_t location_cancellation_req_other[] = {
535 0x1c,
536 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
537 0x06, 0x01, 0x00,
538 };
539
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100540 static const uint8_t purge_ms_err[] = {
541 0x0d,
542 TEST_GSUP_IMSI1_IE,
543 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
544 };
545
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100546 static const uint8_t purge_ms_err_no_cause[] = {
547 0x0d,
548 TEST_GSUP_IMSI1_IE,
549 };
550
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100551 static const uint8_t purge_ms_res[] = {
552 0x0e,
553 TEST_GSUP_IMSI1_IE,
554 0x07, 0x00,
555 };
556
557
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100558 static const uint8_t insert_data_req[] = {
559 0x10,
560 TEST_GSUP_IMSI1_IE,
561 0x05, 0x11,
562 0x10, 0x01, 0x03,
563 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
564 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
565 };
566
567 static const uint8_t delete_data_req[] = {
568 0x14,
569 TEST_GSUP_IMSI1_IE,
570 0x10, 0x01, 0x03,
571 };
572
Neels Hofmeyr241bda02016-06-20 18:26:15 +0200573 printf("Testing subscriber GSUP handling\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100574
575 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
576
577 /* Check for emptiness */
578 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
579
580 /* Allocate entry 1 */
581 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100582 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100583 s1found = gprs_subscr_get_by_imsi(imsi1);
584 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100585 gprs_subscr_put(s1found);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100586
587 /* Create a context */
588 OSMO_ASSERT(count(gprs_llme_list()) == 0);
589 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100590
591 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100592 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100593 ctx->subscr->sgsn_data->mm = ctx;
594
595 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100596 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100597 OSMO_ASSERT(rc >= 0);
598 OSMO_ASSERT(last_updated_subscr == s1);
599
600 /* Check triplets */
601 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
602 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
603 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
604
605 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100606 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100607 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100608 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100609 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100610
611 /* Check triplets */
612 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
613 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
614 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
615
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100616 /* Inject UpdateLocRes GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100617 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100618 OSMO_ASSERT(rc >= 0);
619 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100620 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100621 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400622 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
623 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100624 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
625 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
626 struct sgsn_subscriber_pdp_data, list);
627 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
628 pdpd = llist_entry(pdpd->list.next,
629 struct sgsn_subscriber_pdp_data, list);
630 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100631
632 /* Check authorization */
633 OSMO_ASSERT(s1->authorized == 1);
634
635 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100636 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100637 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100638 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100639 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100640
641 /* Check authorization */
642 OSMO_ASSERT(s1->authorized == 0);
643
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100644 /* Inject InsertSubscrData GSUP message */
645 last_updated_subscr = NULL;
646 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Harald Weltec346f872016-11-26 14:58:36 +0100647 OSMO_ASSERT(rc == -ENOTSUP); /* not connected */
Harald Weltecd5e5262016-05-06 13:46:21 +0200648 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100649
650 /* Inject DeleteSubscrData GSUP message */
651 last_updated_subscr = NULL;
652 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
Maxa66d8cf2017-02-15 11:43:59 +0100653 if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
654 printf("Unexpected response to DSD: %d\n", rc);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100655 OSMO_ASSERT(last_updated_subscr == NULL);
656
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100657 /* Inject wrong LocCancelReq GSUP message */
658 last_updated_subscr = NULL;
659 rc = rx_gsup_message(location_cancellation_req_other,
660 sizeof(location_cancellation_req_other));
661 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
662 OSMO_ASSERT(last_updated_subscr == NULL);
663
664 /* Check cancellation result */
665 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
666 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
667
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100668 /* Inject LocCancelReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100669 rc = rx_gsup_message(location_cancellation_req,
670 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100671 OSMO_ASSERT(rc >= 0);
672 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100673 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100674
675 /* Check cancellation result */
676 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
677 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
678
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200679 /* Inject LocCancelReq(withdraw) GSUP message */
680 rc = rx_gsup_message(location_cancellation_req_withdraw,
681 sizeof(location_cancellation_req_withdraw));
682 OSMO_ASSERT(rc >= 0);
683 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
684
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100685 /* Inject PurgeMsRes GSUP message */
686 rc = rx_gsup_message(purge_ms_res,
687 sizeof(purge_ms_res));
688 OSMO_ASSERT(rc >= 0);
689 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
690
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100691 /* Free MM context and subscriber */
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +0100692 OSMO_ASSERT(ctx->subscr == NULL);
693 sgsn_mm_ctx_cleanup_free(ctx);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100694 gprs_subscr_put(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100695 s1found = gprs_subscr_get_by_imsi(imsi1);
696 OSMO_ASSERT(s1found == NULL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100697
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100698 /* Inject PurgeMsRes GSUP message */
699 rc = rx_gsup_message(purge_ms_res,
700 sizeof(purge_ms_res));
701 OSMO_ASSERT(rc >= 0);
702
703 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
704 rc = rx_gsup_message(purge_ms_err,
705 sizeof(purge_ms_err));
706 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
707
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100708 /* Inject PurgeMsErr() GSUP message */
709 rc = rx_gsup_message(purge_ms_err_no_cause,
710 sizeof(purge_ms_err_no_cause));
711 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
712
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100713 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
714 last_updated_subscr = NULL;
715 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100716 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100717 OSMO_ASSERT(last_updated_subscr == NULL);
718
719 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
720 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
721 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
722 OSMO_ASSERT(last_updated_subscr == NULL);
723
724 /* Inject LocCancelReq GSUP message (unknown IMSI) */
725 rc = rx_gsup_message(location_cancellation_req,
726 sizeof(location_cancellation_req));
727 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
728 OSMO_ASSERT(last_updated_subscr == NULL);
729
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100730 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200731
732 cleanup_test();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100733}
734
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200735int my_gsup_client_send_dummy(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100736{
737 msgb_free(msg);
738 return 0;
739};
740
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200741/*
742 * Test that a GMM Detach will remove the MMCTX and the
743 * associated LLME.
744 */
745static void test_gmm_detach(void)
746{
747 struct gprs_ra_id raid = { 0, };
748 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200749 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200750
751 printf("Testing GMM detach\n");
752
753 /* DTAP - Detach Request (MO) */
754 /* normal detach, power_off = 0 */
755 static const unsigned char detach_req[] = {
756 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
757 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
758 };
759
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200760 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200761
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100762 /* Create a context */
763 OSMO_ASSERT(count(gprs_llme_list()) == 0);
764 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200765
766 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100767 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100768 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200769
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100770 /* verify that a single message (hopefully the Detach Accept) has been
771 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100772 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100773
774 /* verify that things are gone */
775 OSMO_ASSERT(count(gprs_llme_list()) == 0);
776 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
777 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200778
779 cleanup_test();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100780}
781
782/*
783 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
784 * will not sent a Detach Accept message (power_off = 1)
785 */
786static void test_gmm_detach_power_off(void)
787{
788 struct gprs_ra_id raid = { 0, };
789 struct sgsn_mm_ctx *ctx, *ictx;
790 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100791
792 printf("Testing GMM detach (power off)\n");
793
794 /* DTAP - Detach Request (MO) */
795 /* normal detach, power_off = 1 */
796 static const unsigned char detach_req[] = {
797 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
798 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
799 };
800
801 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
802
803 /* Create a context */
804 OSMO_ASSERT(count(gprs_llme_list()) == 0);
805 ctx = alloc_mm_ctx(local_tlli, &raid);
806
807 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100808 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100809 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100810
811 /* verify that no message (and therefore no Detach Accept) has been
812 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100813 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100814
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200815 /* verify that things are gone */
816 OSMO_ASSERT(count(gprs_llme_list()) == 0);
817 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200818 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200819
820 cleanup_test();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200821}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200822
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200823/*
824 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
825 */
826static void test_gmm_detach_no_mmctx(void)
827{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100828 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200829 struct gprs_llc_lle *lle;
830 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200831
832 printf("Testing GMM detach (no MMCTX)\n");
833
834 /* DTAP - Detach Request (MO) */
835 /* normal detach, power_off = 0 */
836 static const unsigned char detach_req[] = {
837 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
838 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
839 };
840
841 /* Create an LLME */
842 OSMO_ASSERT(count(gprs_llme_list()) == 0);
843 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
844 lle = gprs_lle_get_or_create(local_tlli, 3);
845
846 OSMO_ASSERT(count(gprs_llme_list()) == 1);
847
848 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100849 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100850 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200851
852 /* verify that the LLME is gone */
853 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200854
855 cleanup_test();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200856}
857
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100858/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100859 * Test that a single GMM Detach Accept message will not cause the SGSN to send
860 * any message or leave an MM context at the SGSN.
861 */
862static void test_gmm_detach_accept_unexpected(void)
863{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100864 struct gprs_ra_id raid = { 0, };
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100865 struct gprs_llc_lle *lle;
866 uint32_t local_tlli;
867
868 printf("Testing GMM detach accept (unexpected)\n");
869
870 /* DTAP - Detach Accept (MT) */
871 /* normal detach */
872 static const unsigned char detach_acc[] = {
873 0x08, 0x06
874 };
875
876 /* Create an LLME */
877 OSMO_ASSERT(count(gprs_llme_list()) == 0);
878 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
879 lle = gprs_lle_get_or_create(local_tlli, 3);
880
881 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100882 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100883 detach_acc, ARRAY_SIZE(detach_acc));
884
885 /* verify that no message (and therefore no Status or XID reset) has been
886 * sent by the SGSN */
887 OSMO_ASSERT(sgsn_tx_counter == 0);
888
889 /* verify that things are gone */
890 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200891
892 cleanup_test();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100893}
894
895/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100896 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
897 */
898static void test_gmm_status_no_mmctx(void)
899{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100900 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100901 struct gprs_llc_lle *lle;
902 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100903
904 printf("Testing GMM Status (no MMCTX)\n");
905
906 /* DTAP - GMM Status, protocol error */
907 static const unsigned char gmm_status[] = {
908 0x08, 0x20, 0x6f
909 };
910
911 /* Create an LLME */
912 OSMO_ASSERT(count(gprs_llme_list()) == 0);
913 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
914 lle = gprs_lle_get_or_create(local_tlli, 3);
915
916 OSMO_ASSERT(count(gprs_llme_list()) == 1);
917
918 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100919 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100920 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100921
922 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100923 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100924
925 /* verify that the LLME is gone */
926 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200927
928 cleanup_test();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100929}
930
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100931int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
932{
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100933 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100934 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100935 if (rc == -ENOTSUP) {
936 OSMO_ASSERT(mmctx->subscr);
937 gprs_subscr_update(mmctx->subscr);
938 }
939 return rc;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100940}
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100941
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100942int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
943 const uint8_t *auts_rand)
944{
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100945 gprs_subscr_update(mmctx->subscr);
946 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100947}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100948
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100949int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
950 const uint8_t *auts_rand)
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100951{
952 /* Fake an authentication */
953 OSMO_ASSERT(mmctx->subscr);
Neels Hofmeyraa4ed672018-04-22 19:29:41 +0200954 mmctx->sec_ctx = OSMO_AUTH_TYPE_GSM;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100955 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100956
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100957 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100958}
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100959
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200960int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand)
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100961{
962 struct gsm_auth_tuple at = {
Harald Welte121e9a42016-04-20 13:13:19 +0200963 .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
Neels Hofmeyr058cd572017-02-24 06:24:45 +0100964 .vec.auth_types = OSMO_AUTH_TYPE_GSM,
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100965 .key_seq = 0
966 };
967
968 /* Fake an authentication */
969 OSMO_ASSERT(mmctx->subscr);
970 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
971
972 gprs_subscr_update_auth_info(mmctx->subscr);
973
974 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100975}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100976
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100977#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
978 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
979
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100980static int auth_info_skip = 0;
981static int upd_loc_skip = 0;
982
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100983int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
984 const uint8_t *auts_rand)
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100985{
986 static const uint8_t send_auth_info_res[] = {
987 0x0a,
988 TEST_GSUP_IMSI_LONG_IE,
989 0x03, 0x22, /* Auth tuple */
990 0x20, 0x10,
991 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
992 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
993 0x21, 0x04,
994 0x51, 0xe5, 0x51, 0xe5,
995 0x22, 0x08,
996 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
997 };
998
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100999 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001000
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001001 if (auth_info_skip > 0) {
1002 auth_info_skip -= 1;
1003 return -EAGAIN;
1004 }
1005
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001006 /* Fake an SendAuthInfoRes */
1007 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1008
1009 return 0;
1010};
1011
1012int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1013 static const uint8_t update_location_res[] = {
1014 0x06,
1015 TEST_GSUP_IMSI_LONG_IE,
1016 0x04, 0x00, /* PDP info complete */
1017 0x05, 0x12,
1018 0x10, 0x01, 0x01,
1019 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1020 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freyther20de3ae2015-05-05 22:52:40 +02001021 0x08, 0x07, /* MSISDN 49166213323 encoded */
1022 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freyther10c0f562015-05-17 20:58:40 +02001023 0x09, 0x07, /* MSISDN 38166213323 encoded */
1024 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001025 };
1026
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001027 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001028
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001029 if (upd_loc_skip > 0) {
1030 upd_loc_skip -= 1;
1031 return -EAGAIN;
1032 }
1033
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001034 /* Fake an UpdateLocRes */
1035 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1036};
1037
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001038int my_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001039{
Harald Welte23d77d52016-04-25 19:07:34 +02001040 struct osmo_gsup_message to_peer = {0};
1041 struct osmo_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001042 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001043 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001044
1045 /* Simulate the GSUP peer */
Harald Welte23d77d52016-04-25 19:07:34 +02001046 rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001047 OSMO_ASSERT(rc >= 0);
1048 OSMO_ASSERT(to_peer.imsi[0] != 0);
Neels Hofmeyr59504dc2017-01-13 03:10:54 +01001049 osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001050
1051 /* This invalidates the pointers in to_peer */
1052 msgb_free(msg);
1053
1054 switch (to_peer.message_type) {
Harald Welte23d77d52016-04-25 19:07:34 +02001055 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001056 /* Send UPDATE_LOCATION_RESULT */
1057 return my_subscr_request_update_gsup_auth(NULL);
1058
Harald Welte23d77d52016-04-25 19:07:34 +02001059 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001060 /* Send SEND_AUTH_INFO_RESULT */
Pau Espin Pedrol0b050392018-01-07 18:05:22 +01001061 return my_subscr_request_auth_info_gsup_auth(NULL, NULL, NULL);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001062
Harald Welte23d77d52016-04-25 19:07:34 +02001063 case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
1064 from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001065 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001066
1067 default:
1068 if ((to_peer.message_type & 0b00000011) == 0) {
1069 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001070 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001071 from_peer.message_type = to_peer.message_type + 1;
1072 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1073 break;
1074 }
1075
1076 /* Ignore it */
1077 return 0;
1078 }
1079
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001080 reply_msg = osmo_gsup_client_msgb_alloc();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001081 reply_msg->l2h = reply_msg->data;
Harald Welte23d77d52016-04-25 19:07:34 +02001082 osmo_gsup_encode(reply_msg, &from_peer);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001083 gprs_subscr_rx_gsup_message(reply_msg);
1084 msgb_free(reply_msg);
1085
1086 return 0;
1087};
1088
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001089/*
1090 * Test the GMM Rejects
1091 */
1092static void test_gmm_reject(void)
1093{
1094 struct gprs_ra_id raid = { 0, };
1095 struct sgsn_mm_ctx *ctx = NULL;
1096 uint32_t foreign_tlli;
1097 struct gprs_llc_lle *lle;
1098 int idx;
1099
1100 /* DTAP - Attach Request */
1101 /* Invalid MI length */
1102 static const unsigned char attach_req_inv_mi_len[] = {
1103 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1104 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1105 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1106 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1107 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1108 };
1109
1110 /* DTAP - Attach Request */
1111 /* Invalid MI type (IMEI) */
1112 static const unsigned char attach_req_inv_mi_type[] = {
1113 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1114 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1115 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1116 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1117 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1118 };
1119
1120 /* DTAP - Routing Area Update Request */
1121 static const unsigned char dtap_ra_upd_req[] = {
1122 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1123 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1124 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1125 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1126 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1127 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1128 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1129 };
1130
1131 /* DTAP - Routing Area Update Request */
1132 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1133 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1134 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1135 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1136 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1137 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1138 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1139 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1140 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1141 };
1142
1143 /* DTAP - Routing Area Update Request */
1144 /* Invalid cap length */
1145 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1146 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1147 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1150 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1151 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1152 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1153 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1154 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1155 };
1156
1157 struct test {
1158 const char *title;
1159 const unsigned char *msg;
1160 unsigned msg_len;
1161 unsigned num_resp;
1162
1163 };
1164 static struct test tests[] = {
1165 {
1166 .title = "Attach Request (invalid MI length)",
1167 .msg = attach_req_inv_mi_len,
1168 .msg_len = sizeof(attach_req_inv_mi_len),
1169 .num_resp = 1 /* Reject */
1170
1171 },
1172 {
1173 .title = "Attach Request (invalid MI type)",
1174 .msg = attach_req_inv_mi_type,
1175 .msg_len = sizeof(attach_req_inv_mi_type),
1176 .num_resp = 1 /* Reject */
1177 },
1178 {
1179 .title = "Routing Area Update Request (valid)",
1180 .msg = dtap_ra_upd_req,
1181 .msg_len = sizeof(dtap_ra_upd_req),
1182 .num_resp = 2 /* XID Reset + Reject */
1183 },
1184 {
1185 .title = "Routing Area Update Request (invalid type)",
1186 .msg = dtap_ra_upd_req_inv_type,
1187 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1188 .num_resp = 1 /* Reject */
1189 },
1190 {
1191 .title = "Routing Area Update Request (invalid CAP length)",
1192 .msg = dtap_ra_upd_req_inv_cap_len,
1193 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1194 .num_resp = 1 /* Reject */
1195 },
1196 };
1197
1198 printf("Testing GMM reject\n");
1199
1200 /* reset the PRNG used by sgsn_alloc_ptmsi */
1201 srand(1);
1202
1203 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1204
1205 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1206
1207 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1208 const struct test *test = &tests[idx];
1209 printf(" - %s\n", test->title);
1210
1211 /* Create a LLE/LLME */
1212 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1213 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1214
1215 /* Inject the Request message */
Jacob Erlbeck91580892016-01-04 18:43:33 +01001216 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001217 test->msg, test->msg_len);
1218
1219 /* We expect a Reject message */
1220 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1221 sgsn_tx_counter, test->num_resp);
1222 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1223
1224 /* verify that LLME/MM are removed */
1225 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1226 OSMO_ASSERT(ctx == NULL);
1227 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1228 }
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001229
1230 cleanup_test();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001231}
1232
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001233/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001234 * Test cancellation of attached MM contexts
1235 */
1236static void test_gmm_cancel(void)
1237{
1238 struct gprs_ra_id raid = { 0, };
1239 struct sgsn_mm_ctx *ctx = NULL;
1240 struct sgsn_mm_ctx *ictx;
1241 uint32_t ptmsi1;
1242 uint32_t foreign_tlli;
1243 uint32_t local_tlli = 0;
1244 struct gprs_llc_lle *lle;
1245 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1246
1247 /* DTAP - Attach Request */
1248 /* The P-TMSI is not known by the SGSN */
1249 static const unsigned char attach_req[] = {
1250 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1251 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1252 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1253 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1254 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1255 };
1256
1257 /* DTAP - Identity Response IMEI */
1258 static const unsigned char ident_resp_imei[] = {
1259 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1260 0x56
1261 };
1262
1263 /* DTAP - Identity Response IMSI */
1264 static const unsigned char ident_resp_imsi[] = {
1265 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1266 0x54
1267 };
1268
1269 /* DTAP - Attach Complete */
1270 static const unsigned char attach_compl[] = {
1271 0x08, 0x03
1272 };
1273
1274 printf("Testing cancellation\n");
1275
1276 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1277
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001278 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1279
1280 /* Create a LLE/LLME */
1281 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1282 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1283 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1284
1285 /* inject the attach request */
Jacob Erlbeck91580892016-01-04 18:43:33 +01001286 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001287 attach_req, ARRAY_SIZE(attach_req));
1288
1289 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1290 OSMO_ASSERT(ctx != NULL);
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001291 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001292
1293 /* we expect an identity request (IMEI) */
1294 OSMO_ASSERT(sgsn_tx_counter == 1);
1295
1296 /* inject the identity response (IMEI) */
Harald Weltef97ee042015-12-25 19:12:21 +01001297 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001298 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1299
1300 /* we expect an identity request (IMSI) */
1301 OSMO_ASSERT(sgsn_tx_counter == 1);
1302
1303 /* inject the identity response (IMSI) */
Harald Weltef97ee042015-12-25 19:12:21 +01001304 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001305 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1306
1307 /* check that the MM context has not been removed due to a failed
1308 * authorization */
1309 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1310
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001311 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001312
1313 /* we expect an attach accept/reject */
1314 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck133e8622015-10-12 19:36:32 +02001315 ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
1316 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001317
1318 /* this has been randomly assigned by the SGSN */
1319 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1320
1321 /* inject the attach complete */
Harald Weltef97ee042015-12-25 19:12:21 +01001322 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001323 attach_compl, ARRAY_SIZE(attach_compl));
1324
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001325 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001326
1327 /* we don't expect a response */
1328 OSMO_ASSERT(sgsn_tx_counter == 0);
1329
1330 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001331 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001332
1333 /* verify that things are gone */
1334 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1335 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1336 OSMO_ASSERT(!ictx);
1337
1338 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001339
1340 cleanup_test();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001341}
1342
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001343static void test_apn_matching(void)
1344{
1345 struct apn_ctx *actx, *actxs[9];
1346
1347 printf("Testing APN matching\n");
1348
1349 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1350 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1351 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1352 actxs[3] = NULL;
1353
1354 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1355 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1356 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1357 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1358
1359 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1360
1361 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1362 OSMO_ASSERT(actx == actxs[2]);
1363 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1364 OSMO_ASSERT(actx == actxs[2]);
1365 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1366 OSMO_ASSERT(actx == actxs[1]);
1367 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1368 OSMO_ASSERT(actx == actxs[1]);
1369 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1370 OSMO_ASSERT(actx == actxs[0]);
1371 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1372 OSMO_ASSERT(actx == NULL);
1373
1374 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1375 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1376 OSMO_ASSERT(actx == actxs[3]);
1377
1378 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1379 OSMO_ASSERT(actx == actxs[4]);
1380
1381 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1382 OSMO_ASSERT(actx == actxs[6]);
1383
1384 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1385 OSMO_ASSERT(actx == actxs[5]);
1386
1387 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1388 OSMO_ASSERT(actx == actxs[7]);
1389
1390 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1391 OSMO_ASSERT(actx == actxs[8]);
1392
1393 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1394 OSMO_ASSERT(actx == actxs[7]);
1395
1396 /* Free APN contexts and check how the matching changes */
1397
1398 sgsn_apn_ctx_free(actxs[7]);
1399 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1400 OSMO_ASSERT(actx == actxs[8]);
1401
1402 sgsn_apn_ctx_free(actxs[8]);
1403 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1404 OSMO_ASSERT(actx == actxs[6]);
1405
1406 sgsn_apn_ctx_free(actxs[6]);
1407 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1408 OSMO_ASSERT(actx == actxs[1]);
1409
1410 sgsn_apn_ctx_free(actxs[5]);
1411 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1412 OSMO_ASSERT(actx == actxs[4]);
1413
1414 sgsn_apn_ctx_free(actxs[4]);
1415 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1416 OSMO_ASSERT(actx == actxs[2]);
1417
1418 sgsn_apn_ctx_free(actxs[2]);
1419 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1420 OSMO_ASSERT(actx == actxs[1]);
1421
1422 sgsn_apn_ctx_free(actxs[1]);
1423 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1424 OSMO_ASSERT(actx == actxs[0]);
1425
1426 sgsn_apn_ctx_free(actxs[0]);
1427 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1428 OSMO_ASSERT(actx == actxs[3]);
1429
1430 sgsn_apn_ctx_free(actxs[3]);
1431 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1432 OSMO_ASSERT(actx == NULL);
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001433
1434 cleanup_test();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001435}
1436
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001437struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1438 struct sgsn_subscriber_data *sdata);
1439
1440static void test_ggsn_selection(void)
1441{
1442 struct apn_ctx *actxs[4];
1443 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001444 struct gprs_subscr *s1;
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001445 const char *imsi1 = "1234567890";
1446 struct sgsn_mm_ctx *ctx;
1447 struct gprs_ra_id raid = { 0, };
1448 uint32_t local_tlli = 0xffeeddcc;
1449 enum gsm48_gsm_cause gsm_cause;
1450 struct tlv_parsed tp;
1451 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1452 struct sgsn_subscriber_pdp_data *pdp_data;
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001453 char apn_str[GSM_APN_LENGTH];
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001454
1455 printf("Testing GGSN selection\n");
1456
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001457 osmo_gsup_client_send_cb = my_gsup_client_send_dummy;
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001458
1459 /* Check for emptiness */
1460 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1461
1462 /* Create a context */
1463 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1464 ctx = alloc_mm_ctx(local_tlli, &raid);
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001465 osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001466
1467 /* Allocate and attach a subscriber */
1468 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1469 assert_subscr(s1, imsi1);
1470
1471 tp.lv[GSM48_IE_GSM_APN].len = 0;
1472 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1473
1474 /* TODO: Add PDP info entries to s1 */
1475
1476 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1477 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1478 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1479
1480 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1481 actxs[0]->ggsn = ggcs[0];
1482 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1483 actxs[1]->ggsn = ggcs[1];
1484 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1485 actxs[2]->ggsn = ggcs[2];
1486
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001487 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1488 pdp_data->context_id = 1;
1489 pdp_data->pdp_type = 0x0121;
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001490 osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001491
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001492 /* Resolve GGSNs */
1493
1494 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001495 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001496
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001497 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001498 OSMO_ASSERT(ggc != NULL);
1499 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001500 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001501
1502 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001503 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001504
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001505 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001506 OSMO_ASSERT(ggc != NULL);
1507 OSMO_ASSERT(ggc->id == 1);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001508 OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001509
1510 tp.lv[GSM48_IE_GSM_APN].len = 0;
1511 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1512
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001513 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001514 OSMO_ASSERT(ggc != NULL);
1515 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001516 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001517
1518 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1519 actxs[3]->ggsn = ggcs[2];
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001520 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001521 OSMO_ASSERT(ggc != NULL);
1522 OSMO_ASSERT(ggc->id == 2);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001523 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001524
1525 sgsn_apn_ctx_free(actxs[3]);
1526 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1527
1528 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001529 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Foo.Bar");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001530
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001531 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001532 OSMO_ASSERT(ggc == NULL);
1533 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001534 OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001535
1536 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001537 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001538 OSMO_ASSERT(ggc == NULL);
1539 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1540
1541 /* Add PDP data entry to subscriber */
1542
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001543 osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001544
1545 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001546 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001547
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001548 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001549 OSMO_ASSERT(ggc != NULL);
1550 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001551 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001552
1553 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001554 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001555
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001556 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001557 OSMO_ASSERT(ggc == NULL);
1558 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001559 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001560
1561 /* Cleanup */
1562
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001563 gprs_subscr_put(s1);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001564 sgsn_mm_ctx_cleanup_free(ctx);
1565
1566 assert_no_subscrs();
1567
1568 sgsn_apn_ctx_free(actxs[0]);
1569 sgsn_apn_ctx_free(actxs[1]);
1570 sgsn_apn_ctx_free(actxs[2]);
1571
1572 sgsn_ggsn_ctx_free(ggcs[0]);
1573 sgsn_ggsn_ctx_free(ggcs[1]);
1574 sgsn_ggsn_ctx_free(ggcs[2]);
1575
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001576 osmo_gsup_client_send_cb = __real_osmo_gsup_client_send;
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001577
1578 cleanup_test();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001579}
1580
efistokldef0d942019-04-23 14:37:13 +03001581bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
1582
1583static void test_pdp_status_has_active_nsapis(void)
1584{
1585 const size_t pdp_status_len = 2;
1586 const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
1587 const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
1588 const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
1589
1590 printf("Testing pdp_status_has_active_nsapis\n");
1591
1592 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
1593 OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
1594 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
1595}
1596
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001597static struct log_info_cat gprs_categories[] = {
1598 [DMM] = {
1599 .name = "DMM",
1600 .description = "Layer3 Mobility Management (MM)",
1601 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001602 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001603 },
1604 [DPAG] = {
1605 .name = "DPAG",
1606 .description = "Paging Subsystem",
1607 .color = "\033[1;38m",
1608 .enabled = 1, .loglevel = LOGL_NOTICE,
1609 },
1610 [DMEAS] = {
1611 .name = "DMEAS",
1612 .description = "Radio Measurement Processing",
1613 .enabled = 0, .loglevel = LOGL_NOTICE,
1614 },
1615 [DREF] = {
1616 .name = "DREF",
1617 .description = "Reference Counting",
1618 .enabled = 0, .loglevel = LOGL_NOTICE,
1619 },
1620 [DGPRS] = {
1621 .name = "DGPRS",
1622 .description = "GPRS Packet Service",
1623 .enabled = 1, .loglevel = LOGL_DEBUG,
1624 },
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001625 [DLLC] = {
1626 .name = "DLLC",
1627 .description = "GPRS Logical Link Control Protocol (LLC)",
1628 .enabled = 1, .loglevel = LOGL_DEBUG,
1629 },
1630 [DSNDCP] = {
1631 .name = "DSNDCP",
1632 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1633 .enabled = 1, .loglevel = LOGL_DEBUG,
1634 },
1635};
1636
1637static struct log_info info = {
1638 .cat = gprs_categories,
1639 .num_cat = ARRAY_SIZE(gprs_categories),
1640};
1641
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001642static struct vty_app_info vty_info = {
1643 .name = "testSGSN",
1644};
1645
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001646int main(int argc, char **argv)
1647{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001648 void *osmo_sgsn_ctx;
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001649 void *msgb_ctx;
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001650
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001651 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
Neels Hofmeyr5bd340e2018-04-16 00:57:10 +02001652 osmo_init_logging2(osmo_sgsn_ctx, &info);
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +01001653 tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001654 msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001655
Alexander Couzens14314bd2016-07-05 09:52:52 +02001656 sgsn_rate_ctr_init();
Max2e485762018-12-10 18:01:47 +01001657 sgsn_auth_init(sgsn);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001658 gprs_subscr_init(sgsn);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001659 vty_init(&vty_info);
1660 sgsn_vty_init(&sgsn->cfg);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001661
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001662 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001663 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001664 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001665 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001666 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001667 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001668 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001669 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001670 test_gmm_status_no_mmctx();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001671 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001672 test_gmm_cancel();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001673 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001674 test_ggsn_selection();
efistokldef0d942019-04-23 14:37:13 +03001675 test_pdp_status_has_active_nsapis();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001676 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001677
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001678 talloc_report_full(osmo_sgsn_ctx, stderr);
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001679 OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +01001680 OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 2);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001681 return 0;
1682}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001683
1684
1685/* stubs */
1686struct osmo_prim_hdr;
1687int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1688{
1689 abort();
1690}