blob: 44218de05c7626e7206ab64538da6039cc0e193a [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>
Pau Espin Pedrol5f4736a2023-01-04 21:30:28 +010041#include <osmocom/sgsn/gtp_ggsn.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020042
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020043#include <stdio.h>
44
Pau Espin Pedrol749ca7c2022-12-22 19:49:37 +010045#include "gprs_gb_parse.h"
46
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010047void *tall_sgsn_ctx;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020048static struct sgsn_instance sgsn_inst = {
49 .config_file = "osmo_sgsn.cfg",
50 .cfg = {
51 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010052 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Neels Hofmeyr340a7e92022-03-07 15:37:24 +010053 .gea_encryption_mask = 0x1,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020054 },
55};
56struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010057unsigned sgsn_tx_counter = 0;
Jacob Erlbeck133e8622015-10-12 19:36:32 +020058struct msgb *last_msg = NULL;
59struct gprs_gb_parse_context last_dl_parse_ctx;
60
61static void reset_last_msg()
62{
63 if (last_msg)
64 msgb_free(last_msg);
65
66 last_msg = NULL;
67 memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
68}
Jacob Erlbeck189999d2014-10-27 14:34:13 +010069
Jacob Erlbeckcf151872015-10-12 19:36:31 +020070static void cleanup_test()
71{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020072 reset_last_msg();
73}
74
75static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
76{
77 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
78
79 if (parse_ctx->new_ptmsi_enc)
80 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
81
82 return new_ptmsi;
Jacob Erlbeckcf151872015-10-12 19:36:31 +020083}
84
Jacob Erlbeck189999d2014-10-27 14:34:13 +010085/* override */
86int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
87 struct bssgp_dl_ud_par *dup)
88{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020089 int rc;
90
91 reset_last_msg();
92
93 last_msg = msg;
94 OSMO_ASSERT(msgb_data(last_msg) != NULL);
95
96 rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
97 &last_dl_parse_ctx);
98
99 fprintf(stderr, "Got DL LLC message: %s\n",
100 gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
101
102 OSMO_ASSERT(rc > 0);
103
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100104 sgsn_tx_counter += 1;
105 return 0;
106}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200107
Max3b6332f2017-11-01 13:28:38 +0100108/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
109int __real_osmo_get_rand_id(uint8_t *data, size_t len);
110int mock_osmo_get_rand_id(uint8_t *data, size_t len);
111int (*osmo_get_rand_id_cb)(uint8_t *, size_t) =
112 &mock_osmo_get_rand_id;
Max4011e722016-07-05 15:19:12 +0200113
Max3b6332f2017-11-01 13:28:38 +0100114int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200115{
Max3b6332f2017-11-01 13:28:38 +0100116 return (*osmo_get_rand_id_cb)(buf, num);
Max4011e722016-07-05 15:19:12 +0200117}
118/* make results of A&C ref predictable */
Max3b6332f2017-11-01 13:28:38 +0100119int mock_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200120{
121 if (num > 1)
Max3b6332f2017-11-01 13:28:38 +0100122 return __real_osmo_get_rand_id(buf, num);
Max4011e722016-07-05 15:19:12 +0200123 buf[0] = 0;
124 return 1;
125}
126
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100127/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100128void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
129void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100130 &__real_sgsn_update_subscriber_data;
131
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100132void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100133{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100134 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100135}
136
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100137/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
138int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
139int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
140 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100141
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100142int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
143 return (*subscr_request_update_location_cb)(mmctx);
144};
145
146/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200147int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
148int (*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 +0100149 &__real_gprs_subscr_request_auth_info;
150
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200151int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
152 return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100153};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100154
Neels Hofmeyr814fef02016-12-08 21:19:57 +0100155/* override, requires '-Wl,--wrap=gsup_client_send' */
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200156int __real_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
157int (*osmo_gsup_client_send_cb)(struct osmo_gsup_client *gsupc, struct msgb *msg) =
158 &__real_osmo_gsup_client_send;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100159
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200160int __wrap_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100161{
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200162 return (*osmo_gsup_client_send_cb)(gsupc, msg);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100163};
164
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200165static int count(struct llist_head *head)
166{
167 struct llist_head *cur;
168 int count = 0;
169
170 llist_for_each(cur, head)
171 count += 1;
172
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100173 return count;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200174}
175
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200176static struct msgb *create_msg(const uint8_t *data, size_t len)
177{
178 struct msgb *msg = msgb_alloc(len + 8, "test message");
179 msg->l1h = msgb_put(msg, 8);
180 msg->l2h = msgb_put(msg, len);
181 memcpy(msg->l2h, data, len);
182
183 msgb_bcid(msg) = msg->l1h;
184 msgb_gmmh(msg) = msg->l2h;
185 return msg;
186}
187
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100188/*
189 * Create a context and search for it
190 */
191static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
192{
193 struct sgsn_mm_ctx *ctx, *ictx;
194 struct gprs_llc_lle *lle;
195 int old_count = count(gprs_llme_list());
196
197 lle = gprs_lle_get_or_create(tlli, 3);
Alexander Couzens2b5fb8e2017-02-04 06:01:00 +0100198 ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
Harald Weltef97ee042015-12-25 19:12:21 +0100199 ctx->gb.llme = lle->llme;
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100200
201 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
202 OSMO_ASSERT(ictx == ctx);
203
204 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
205
206 return ctx;
207}
208
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100209static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
Jacob Erlbeck91580892016-01-04 18:43:33 +0100210 const struct gprs_ra_id *bssgp_raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100211 const uint8_t *data, size_t data_len)
212{
213 struct msgb *msg;
214
Jacob Erlbeck133e8622015-10-12 19:36:32 +0200215 reset_last_msg();
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100216 sgsn_tx_counter = 0;
217
218 msg = create_msg(data, data_len);
219 msgb_tlli(msg) = tlli;
Jacob Erlbeck91580892016-01-04 18:43:33 +0100220 bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
Max82040102016-07-06 11:59:18 +0200221 gsm0408_gprs_rcvmsg_gb(msg, llme, false);
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100222 msgb_free(msg);
223}
224
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200225static void test_llme(void)
226{
227 struct gprs_llc_lle *lle, *lle_copy;
228 uint32_t local_tlli;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200229
230 printf("Testing LLME allocations\n");
231 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200232
233 /* initial state */
234 OSMO_ASSERT(count(gprs_llme_list()) == 0);
235
236 /* Create a new entry */
237 lle = gprs_lle_get_or_create(local_tlli, 3);
238 OSMO_ASSERT(lle);
239 OSMO_ASSERT(count(gprs_llme_list()) == 1);
240
241 /* No new entry is created */
242 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
243 OSMO_ASSERT(lle == lle_copy);
244 OSMO_ASSERT(count(gprs_llme_list()) == 1);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200245
246 /* unassign which should delete it*/
Max39550252016-06-28 17:39:20 +0200247 gprs_llgmm_unassign(lle->llme);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200248
249 /* Check that everything was cleaned up */
250 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200251
252 cleanup_test();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200253}
254
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100255struct gprs_subscr *last_updated_subscr = NULL;
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100256void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100257{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100258 OSMO_ASSERT(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100259 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100260 __func__, mmctx, mmctx->subscr);
261 last_updated_subscr = mmctx->subscr;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100262}
263
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100264static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100265{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100266 struct gprs_subscr *sfound;
Jacob Erlbeck6be9ffa2015-01-19 08:57:07 +0100267 OSMO_ASSERT(subscr);
268 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100269
270 sfound = gprs_subscr_get_by_imsi(imsi);
271 OSMO_ASSERT(sfound == subscr);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100272
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100273 gprs_subscr_put(sfound);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100274}
275
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100276static void show_subscrs(FILE *out)
277{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100278 struct gprs_subscr *subscr;
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100279
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100280 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100281 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100282 "use count: %d\n",
283 subscr->imsi, subscr->use_count);
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100284 }
285}
286
287static void assert_no_subscrs()
288{
289 show_subscrs(stdout);
290 fflush(stdout);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100291 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100292}
293
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100294#define VERBOSE_ASSERT(val, expect_op, fmt) \
295 do { \
296 printf(#val " == " fmt "\n", (val)); \
297 OSMO_ASSERT((val) expect_op); \
298 } while (0);
299
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100300static void test_subscriber(void)
301{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100302 struct gprs_subscr *s1, *s2, *s3;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100303 const char *imsi1 = "1234567890";
304 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100305 const char *imsi3 = "5656565656";
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100306
307 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
308
309 printf("Testing core subscriber data API\n");
310
311 /* Check for emptiness */
312 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
313 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100314 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100315 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100316
317 /* Allocate entry 1 */
318 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100319 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
320 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100321 assert_subscr(s1, imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100322 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100323 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100324
325 /* Allocate entry 2 */
326 s2 = gprs_subscr_get_or_create(imsi2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100327 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
328 s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100329
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100330 /* Allocate entry 3 */
331 s3 = gprs_subscr_get_or_create(imsi3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100332 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100333
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100334 /* Check entries */
335 assert_subscr(s1, imsi1);
336 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100337 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100338
339 /* Update entry 1 */
340 last_updated_subscr = NULL;
341 gprs_subscr_update(s1);
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100342 OSMO_ASSERT(last_updated_subscr == NULL);
343 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100344 OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100345
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100346 /* There is no subscriber cache. Verify it */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100347 gprs_subscr_cleanup(s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100348 gprs_subscr_put(s1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100349 s1 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100350 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
351 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100352
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100353 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100354 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100355
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100356 /* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100357 gprs_subscr_cleanup(s2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100358 gprs_subscr_put(s2);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100359 s2 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100360 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100361 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
362 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100363 assert_subscr(s3, imsi3);
364
365 /* Try to delete entry 3 */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100366 gprs_subscr_cleanup(s3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100367 gprs_subscr_put(s3);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100368 s3 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100369 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100370 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100371
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100372 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100373
374 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200375
376 cleanup_test();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100377}
378
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100379static void test_auth_triplets(void)
380{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100381 struct gprs_subscr *s1, *s1found;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100382 const char *imsi1 = "1234567890";
383 struct gsm_auth_tuple *at;
384 struct sgsn_mm_ctx *ctx;
385 struct gprs_ra_id raid = { 0, };
386 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100387
388 printf("Testing authentication triplet handling\n");
389
390 /* Check for emptiness */
391 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
392
393 /* Allocate entry 1 */
394 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100395 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100396 s1found = gprs_subscr_get_by_imsi(imsi1);
397 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100398 gprs_subscr_put(s1found);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100399
400 /* Create a context */
401 OSMO_ASSERT(count(gprs_llme_list()) == 0);
402 ctx = alloc_mm_ctx(local_tlli, &raid);
403
404 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100405 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100406 ctx->subscr->sgsn_data->mm = ctx;
407
408 /* Try to get auth tuple */
409 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
410 OSMO_ASSERT(at == NULL);
411
412 /* Add triplets */
413 s1->sgsn_data->auth_triplets[0].key_seq = 0;
414 s1->sgsn_data->auth_triplets[1].key_seq = 1;
415 s1->sgsn_data->auth_triplets[2].key_seq = 2;
416
417 /* Try to get auth tuple */
418 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
419 OSMO_ASSERT(at != NULL);
420 OSMO_ASSERT(at->key_seq == 0);
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 == 1);
425 OSMO_ASSERT(at->use_count == 1);
426 at = sgsn_auth_get_tuple(ctx, at->key_seq);
427 OSMO_ASSERT(at != NULL);
428 OSMO_ASSERT(at->key_seq == 2);
429 OSMO_ASSERT(at->use_count == 1);
430 at = sgsn_auth_get_tuple(ctx, at->key_seq);
431 OSMO_ASSERT(at == NULL);
432
433 /* Free MM context and subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100434 gprs_subscr_put(s1);
Jacob Erlbecke671d252015-01-26 14:43:07 +0100435 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100436 s1found = gprs_subscr_get_by_imsi(imsi1);
437 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200438
439 cleanup_test();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100440}
441
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100442#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
443
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100444static int rx_gsup_message(const uint8_t *data, size_t data_len)
445{
446 struct msgb *msg;
447 int rc;
448
449 msg = msgb_alloc(1024, __func__);
450 msg->l2h = msgb_put(msg, data_len);
451 OSMO_ASSERT(msg->l2h != NULL);
452 memcpy(msg->l2h, data, data_len);
453 rc = gprs_subscr_rx_gsup_message(msg);
454 msgb_free(msg);
455
456 return rc;
457}
458
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100459static void test_subscriber_gsup(void)
460{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100461 struct gprs_subscr *s1, *s1found;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100462 const char *imsi1 = "1234567890";
463 struct sgsn_mm_ctx *ctx;
464 struct gprs_ra_id raid = { 0, };
465 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100466 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100467 int rc;
468
469 static const uint8_t send_auth_info_res[] = {
470 0x0a,
471 TEST_GSUP_IMSI1_IE,
472 0x03, 0x22, /* Auth tuple */
473 0x20, 0x10,
474 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
475 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
476 0x21, 0x04,
477 0x21, 0x22, 0x23, 0x24,
478 0x22, 0x08,
479 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
480 0x03, 0x22, /* Auth tuple */
481 0x20, 0x10,
482 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
483 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
484 0x21, 0x04,
485 0xa1, 0xa2, 0xa3, 0xa4,
486 0x22, 0x08,
487 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
488 };
489
490 static const uint8_t send_auth_info_err[] = {
491 0x09,
492 TEST_GSUP_IMSI1_IE,
493 0x02, 0x01, 0x07 /* GPRS not allowed */
494 };
495
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400496#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
497
498 static const uint8_t s1_msisdn[] = { MSISDN };
499
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100500 static const uint8_t update_location_res[] = {
501 0x06,
502 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400503 0x08, 0x09, MSISDN,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100504 0x04, 0x00, /* PDP info complete */
505 0x05, 0x12,
506 0x10, 0x01, 0x01,
507 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
508 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
509 0x05, 0x11,
510 0x10, 0x01, 0x02,
511 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
512 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
513 };
514
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400515#undef MSISDN
516
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100517 static const uint8_t update_location_err[] = {
518 0x05,
519 TEST_GSUP_IMSI1_IE,
520 0x02, 0x01, 0x07 /* GPRS not allowed */
521 };
522
523 static const uint8_t location_cancellation_req[] = {
524 0x1c,
525 TEST_GSUP_IMSI1_IE,
526 0x06, 0x01, 0x00,
527 };
528
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200529 static const uint8_t location_cancellation_req_withdraw[] = {
530 0x1c,
531 TEST_GSUP_IMSI1_IE,
532 0x06, 0x01, 0x01,
533 };
534
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100535 static const uint8_t location_cancellation_req_other[] = {
536 0x1c,
537 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
538 0x06, 0x01, 0x00,
539 };
540
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100541 static const uint8_t purge_ms_err[] = {
542 0x0d,
543 TEST_GSUP_IMSI1_IE,
544 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
545 };
546
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100547 static const uint8_t purge_ms_err_no_cause[] = {
548 0x0d,
549 TEST_GSUP_IMSI1_IE,
550 };
551
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100552 static const uint8_t purge_ms_res[] = {
553 0x0e,
554 TEST_GSUP_IMSI1_IE,
555 0x07, 0x00,
556 };
557
558
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100559 static const uint8_t insert_data_req[] = {
560 0x10,
561 TEST_GSUP_IMSI1_IE,
562 0x05, 0x11,
563 0x10, 0x01, 0x03,
564 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
565 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
566 };
567
568 static const uint8_t delete_data_req[] = {
569 0x14,
570 TEST_GSUP_IMSI1_IE,
571 0x10, 0x01, 0x03,
572 };
573
Neels Hofmeyr241bda02016-06-20 18:26:15 +0200574 printf("Testing subscriber GSUP handling\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100575
576 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
577
578 /* Check for emptiness */
579 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
580
581 /* Allocate entry 1 */
582 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100583 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100584 s1found = gprs_subscr_get_by_imsi(imsi1);
585 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100586 gprs_subscr_put(s1found);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100587
588 /* Create a context */
589 OSMO_ASSERT(count(gprs_llme_list()) == 0);
590 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100591
592 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100593 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100594 ctx->subscr->sgsn_data->mm = ctx;
595
596 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100597 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100598 OSMO_ASSERT(rc >= 0);
599 OSMO_ASSERT(last_updated_subscr == s1);
600
601 /* Check triplets */
602 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
603 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
604 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
605
606 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100607 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100608 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100609 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100610 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100611
612 /* Check triplets */
613 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
614 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
615 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
616
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100617 /* Inject UpdateLocRes GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100618 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100619 OSMO_ASSERT(rc >= 0);
620 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100621 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100622 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400623 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
624 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100625 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
626 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
627 struct sgsn_subscriber_pdp_data, list);
628 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
629 pdpd = llist_entry(pdpd->list.next,
630 struct sgsn_subscriber_pdp_data, list);
631 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100632
633 /* Check authorization */
634 OSMO_ASSERT(s1->authorized == 1);
635
636 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100637 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100638 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100639 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100640 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100641
642 /* Check authorization */
643 OSMO_ASSERT(s1->authorized == 0);
644
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100645 /* Inject InsertSubscrData GSUP message */
646 last_updated_subscr = NULL;
647 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Harald Weltec346f872016-11-26 14:58:36 +0100648 OSMO_ASSERT(rc == -ENOTSUP); /* not connected */
Harald Weltecd5e5262016-05-06 13:46:21 +0200649 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100650
651 /* Inject DeleteSubscrData GSUP message */
652 last_updated_subscr = NULL;
653 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
Maxa66d8cf2017-02-15 11:43:59 +0100654 if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
655 printf("Unexpected response to DSD: %d\n", rc);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100656 OSMO_ASSERT(last_updated_subscr == NULL);
657
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100658 /* Inject wrong LocCancelReq GSUP message */
659 last_updated_subscr = NULL;
660 rc = rx_gsup_message(location_cancellation_req_other,
661 sizeof(location_cancellation_req_other));
662 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
663 OSMO_ASSERT(last_updated_subscr == NULL);
664
665 /* Check cancellation result */
666 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
667 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
668
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100669 /* Inject LocCancelReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100670 rc = rx_gsup_message(location_cancellation_req,
671 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100672 OSMO_ASSERT(rc >= 0);
673 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100674 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100675
676 /* Check cancellation result */
677 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
678 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
679
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200680 /* Inject LocCancelReq(withdraw) GSUP message */
681 rc = rx_gsup_message(location_cancellation_req_withdraw,
682 sizeof(location_cancellation_req_withdraw));
683 OSMO_ASSERT(rc >= 0);
684 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
685
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100686 /* Inject PurgeMsRes GSUP message */
687 rc = rx_gsup_message(purge_ms_res,
688 sizeof(purge_ms_res));
689 OSMO_ASSERT(rc >= 0);
690 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
691
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100692 /* Free MM context and subscriber */
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +0100693 OSMO_ASSERT(ctx->subscr == NULL);
694 sgsn_mm_ctx_cleanup_free(ctx);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100695 gprs_subscr_put(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100696 s1found = gprs_subscr_get_by_imsi(imsi1);
697 OSMO_ASSERT(s1found == NULL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100698
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100699 /* Inject PurgeMsRes GSUP message */
700 rc = rx_gsup_message(purge_ms_res,
701 sizeof(purge_ms_res));
702 OSMO_ASSERT(rc >= 0);
703
704 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
705 rc = rx_gsup_message(purge_ms_err,
706 sizeof(purge_ms_err));
707 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
708
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100709 /* Inject PurgeMsErr() GSUP message */
710 rc = rx_gsup_message(purge_ms_err_no_cause,
711 sizeof(purge_ms_err_no_cause));
712 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
713
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100714 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
715 last_updated_subscr = NULL;
716 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100717 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100718 OSMO_ASSERT(last_updated_subscr == NULL);
719
720 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
721 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
722 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
723 OSMO_ASSERT(last_updated_subscr == NULL);
724
725 /* Inject LocCancelReq GSUP message (unknown IMSI) */
726 rc = rx_gsup_message(location_cancellation_req,
727 sizeof(location_cancellation_req));
728 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
729 OSMO_ASSERT(last_updated_subscr == NULL);
730
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100731 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200732
733 cleanup_test();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100734}
735
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200736int my_gsup_client_send_dummy(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100737{
738 msgb_free(msg);
739 return 0;
740};
741
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200742/*
743 * Test that a GMM Detach will remove the MMCTX and the
744 * associated LLME.
745 */
746static void test_gmm_detach(void)
747{
748 struct gprs_ra_id raid = { 0, };
749 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200750 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200751
752 printf("Testing GMM detach\n");
753
754 /* DTAP - Detach Request (MO) */
755 /* normal detach, power_off = 0 */
756 static const unsigned char detach_req[] = {
757 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
758 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
759 };
760
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200761 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200762
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100763 /* Create a context */
764 OSMO_ASSERT(count(gprs_llme_list()) == 0);
765 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200766
767 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100768 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100769 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200770
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100771 /* verify that a single message (hopefully the Detach Accept) has been
772 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100773 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100774
775 /* verify that things are gone */
776 OSMO_ASSERT(count(gprs_llme_list()) == 0);
777 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
778 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200779
780 cleanup_test();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100781}
782
783/*
784 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
785 * will not sent a Detach Accept message (power_off = 1)
786 */
787static void test_gmm_detach_power_off(void)
788{
789 struct gprs_ra_id raid = { 0, };
790 struct sgsn_mm_ctx *ctx, *ictx;
791 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100792
793 printf("Testing GMM detach (power off)\n");
794
795 /* DTAP - Detach Request (MO) */
796 /* normal detach, power_off = 1 */
797 static const unsigned char detach_req[] = {
798 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
799 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
800 };
801
802 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
803
804 /* Create a context */
805 OSMO_ASSERT(count(gprs_llme_list()) == 0);
806 ctx = alloc_mm_ctx(local_tlli, &raid);
807
808 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100809 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100810 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100811
812 /* verify that no message (and therefore no Detach Accept) has been
813 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100814 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100815
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200816 /* verify that things are gone */
817 OSMO_ASSERT(count(gprs_llme_list()) == 0);
818 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200819 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200820
821 cleanup_test();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200822}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200823
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200824/*
825 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
826 */
827static void test_gmm_detach_no_mmctx(void)
828{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100829 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200830 struct gprs_llc_lle *lle;
831 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200832
833 printf("Testing GMM detach (no MMCTX)\n");
834
835 /* DTAP - Detach Request (MO) */
836 /* normal detach, power_off = 0 */
837 static const unsigned char detach_req[] = {
838 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
839 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
840 };
841
842 /* Create an LLME */
843 OSMO_ASSERT(count(gprs_llme_list()) == 0);
844 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
845 lle = gprs_lle_get_or_create(local_tlli, 3);
846
847 OSMO_ASSERT(count(gprs_llme_list()) == 1);
848
849 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100850 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100851 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200852
853 /* verify that the LLME is gone */
854 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200855
856 cleanup_test();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200857}
858
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100859/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100860 * Test that a single GMM Detach Accept message will not cause the SGSN to send
861 * any message or leave an MM context at the SGSN.
862 */
863static void test_gmm_detach_accept_unexpected(void)
864{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100865 struct gprs_ra_id raid = { 0, };
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100866 struct gprs_llc_lle *lle;
867 uint32_t local_tlli;
868
869 printf("Testing GMM detach accept (unexpected)\n");
870
871 /* DTAP - Detach Accept (MT) */
872 /* normal detach */
873 static const unsigned char detach_acc[] = {
874 0x08, 0x06
875 };
876
877 /* Create an LLME */
878 OSMO_ASSERT(count(gprs_llme_list()) == 0);
879 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
880 lle = gprs_lle_get_or_create(local_tlli, 3);
881
882 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100883 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100884 detach_acc, ARRAY_SIZE(detach_acc));
885
886 /* verify that no message (and therefore no Status or XID reset) has been
887 * sent by the SGSN */
888 OSMO_ASSERT(sgsn_tx_counter == 0);
889
890 /* verify that things are gone */
891 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200892
893 cleanup_test();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100894}
895
896/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100897 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
898 */
899static void test_gmm_status_no_mmctx(void)
900{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100901 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100902 struct gprs_llc_lle *lle;
903 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100904
905 printf("Testing GMM Status (no MMCTX)\n");
906
907 /* DTAP - GMM Status, protocol error */
908 static const unsigned char gmm_status[] = {
909 0x08, 0x20, 0x6f
910 };
911
912 /* Create an LLME */
913 OSMO_ASSERT(count(gprs_llme_list()) == 0);
914 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
915 lle = gprs_lle_get_or_create(local_tlli, 3);
916
917 OSMO_ASSERT(count(gprs_llme_list()) == 1);
918
919 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100920 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100921 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100922
923 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100924 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100925
926 /* verify that the LLME is gone */
927 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200928
929 cleanup_test();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100930}
931
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100932int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
933{
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100934 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100935 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100936 if (rc == -ENOTSUP) {
937 OSMO_ASSERT(mmctx->subscr);
938 gprs_subscr_update(mmctx->subscr);
939 }
940 return rc;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100941}
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100942
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100943int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
944 const uint8_t *auts_rand)
945{
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100946 gprs_subscr_update(mmctx->subscr);
947 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100948}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100949
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100950int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
951 const uint8_t *auts_rand)
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100952{
953 /* Fake an authentication */
954 OSMO_ASSERT(mmctx->subscr);
Neels Hofmeyraa4ed672018-04-22 19:29:41 +0200955 mmctx->sec_ctx = OSMO_AUTH_TYPE_GSM;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100956 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100957
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100958 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100959}
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100960
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200961int 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 +0100962{
963 struct gsm_auth_tuple at = {
Harald Welte121e9a42016-04-20 13:13:19 +0200964 .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
Neels Hofmeyr058cd572017-02-24 06:24:45 +0100965 .vec.auth_types = OSMO_AUTH_TYPE_GSM,
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100966 .key_seq = 0
967 };
968
969 /* Fake an authentication */
970 OSMO_ASSERT(mmctx->subscr);
971 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
972
973 gprs_subscr_update_auth_info(mmctx->subscr);
974
975 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100976}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100977
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100978#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
979 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
980
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100981static int auth_info_skip = 0;
982static int upd_loc_skip = 0;
983
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100984int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
985 const uint8_t *auts_rand)
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100986{
987 static const uint8_t send_auth_info_res[] = {
988 0x0a,
989 TEST_GSUP_IMSI_LONG_IE,
990 0x03, 0x22, /* Auth tuple */
991 0x20, 0x10,
992 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
993 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
994 0x21, 0x04,
995 0x51, 0xe5, 0x51, 0xe5,
996 0x22, 0x08,
997 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
998 };
999
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001000 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001001
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001002 if (auth_info_skip > 0) {
1003 auth_info_skip -= 1;
1004 return -EAGAIN;
1005 }
1006
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001007 /* Fake an SendAuthInfoRes */
1008 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1009
1010 return 0;
1011};
1012
1013int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1014 static const uint8_t update_location_res[] = {
1015 0x06,
1016 TEST_GSUP_IMSI_LONG_IE,
1017 0x04, 0x00, /* PDP info complete */
1018 0x05, 0x12,
1019 0x10, 0x01, 0x01,
1020 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1021 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freyther20de3ae2015-05-05 22:52:40 +02001022 0x08, 0x07, /* MSISDN 49166213323 encoded */
1023 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freyther10c0f562015-05-17 20:58:40 +02001024 0x09, 0x07, /* MSISDN 38166213323 encoded */
1025 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001026 };
1027
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001028 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001029
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001030 if (upd_loc_skip > 0) {
1031 upd_loc_skip -= 1;
1032 return -EAGAIN;
1033 }
1034
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001035 /* Fake an UpdateLocRes */
1036 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1037};
1038
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001039int my_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001040{
Harald Welte23d77d52016-04-25 19:07:34 +02001041 struct osmo_gsup_message to_peer = {0};
1042 struct osmo_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001043 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001044 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001045
1046 /* Simulate the GSUP peer */
Harald Welte23d77d52016-04-25 19:07:34 +02001047 rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001048 OSMO_ASSERT(rc >= 0);
1049 OSMO_ASSERT(to_peer.imsi[0] != 0);
Neels Hofmeyr59504dc2017-01-13 03:10:54 +01001050 osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001051
1052 /* This invalidates the pointers in to_peer */
1053 msgb_free(msg);
1054
1055 switch (to_peer.message_type) {
Harald Welte23d77d52016-04-25 19:07:34 +02001056 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001057 /* Send UPDATE_LOCATION_RESULT */
1058 return my_subscr_request_update_gsup_auth(NULL);
1059
Harald Welte23d77d52016-04-25 19:07:34 +02001060 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001061 /* Send SEND_AUTH_INFO_RESULT */
Pau Espin Pedrol0b050392018-01-07 18:05:22 +01001062 return my_subscr_request_auth_info_gsup_auth(NULL, NULL, NULL);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001063
Harald Welte23d77d52016-04-25 19:07:34 +02001064 case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
1065 from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001066 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001067
1068 default:
1069 if ((to_peer.message_type & 0b00000011) == 0) {
1070 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001071 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001072 from_peer.message_type = to_peer.message_type + 1;
1073 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1074 break;
1075 }
1076
1077 /* Ignore it */
1078 return 0;
1079 }
1080
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001081 reply_msg = osmo_gsup_client_msgb_alloc();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001082 reply_msg->l2h = reply_msg->data;
Harald Welte23d77d52016-04-25 19:07:34 +02001083 osmo_gsup_encode(reply_msg, &from_peer);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001084 gprs_subscr_rx_gsup_message(reply_msg);
1085 msgb_free(reply_msg);
1086
1087 return 0;
1088};
1089
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001090/*
1091 * Test the GMM Rejects
1092 */
1093static void test_gmm_reject(void)
1094{
1095 struct gprs_ra_id raid = { 0, };
1096 struct sgsn_mm_ctx *ctx = NULL;
1097 uint32_t foreign_tlli;
1098 struct gprs_llc_lle *lle;
1099 int idx;
1100
1101 /* DTAP - Attach Request */
1102 /* Invalid MI length */
1103 static const unsigned char attach_req_inv_mi_len[] = {
1104 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1105 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1106 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1107 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1108 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1109 };
1110
1111 /* DTAP - Attach Request */
1112 /* Invalid MI type (IMEI) */
1113 static const unsigned char attach_req_inv_mi_type[] = {
1114 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1115 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1116 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1117 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1118 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1119 };
1120
1121 /* DTAP - Routing Area Update Request */
1122 static const unsigned char dtap_ra_upd_req[] = {
1123 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1124 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1125 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1126 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1127 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1128 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1129 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1130 };
1131
1132 /* DTAP - Routing Area Update Request */
1133 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1134 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1135 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1136 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1137 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1138 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1139 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1140 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1141 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1142 };
1143
1144 /* DTAP - Routing Area Update Request */
1145 /* Invalid cap length */
1146 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1147 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1148 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1151 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1152 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1153 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1154 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1155 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1156 };
1157
1158 struct test {
1159 const char *title;
1160 const unsigned char *msg;
1161 unsigned msg_len;
1162 unsigned num_resp;
1163
1164 };
1165 static struct test tests[] = {
1166 {
1167 .title = "Attach Request (invalid MI length)",
1168 .msg = attach_req_inv_mi_len,
1169 .msg_len = sizeof(attach_req_inv_mi_len),
1170 .num_resp = 1 /* Reject */
1171
1172 },
1173 {
1174 .title = "Attach Request (invalid MI type)",
1175 .msg = attach_req_inv_mi_type,
1176 .msg_len = sizeof(attach_req_inv_mi_type),
1177 .num_resp = 1 /* Reject */
1178 },
1179 {
1180 .title = "Routing Area Update Request (valid)",
1181 .msg = dtap_ra_upd_req,
1182 .msg_len = sizeof(dtap_ra_upd_req),
1183 .num_resp = 2 /* XID Reset + Reject */
1184 },
1185 {
1186 .title = "Routing Area Update Request (invalid type)",
1187 .msg = dtap_ra_upd_req_inv_type,
1188 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1189 .num_resp = 1 /* Reject */
1190 },
1191 {
1192 .title = "Routing Area Update Request (invalid CAP length)",
1193 .msg = dtap_ra_upd_req_inv_cap_len,
1194 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1195 .num_resp = 1 /* Reject */
1196 },
1197 };
1198
1199 printf("Testing GMM reject\n");
1200
1201 /* reset the PRNG used by sgsn_alloc_ptmsi */
1202 srand(1);
1203
1204 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1205
1206 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1207
1208 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1209 const struct test *test = &tests[idx];
1210 printf(" - %s\n", test->title);
1211
1212 /* Create a LLE/LLME */
1213 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1214 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1215
1216 /* Inject the Request message */
Jacob Erlbeck91580892016-01-04 18:43:33 +01001217 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001218 test->msg, test->msg_len);
1219
1220 /* We expect a Reject message */
1221 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1222 sgsn_tx_counter, test->num_resp);
1223 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1224
1225 /* verify that LLME/MM are removed */
1226 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1227 OSMO_ASSERT(ctx == NULL);
1228 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1229 }
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001230
1231 cleanup_test();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001232}
1233
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001234/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001235 * Test cancellation of attached MM contexts
1236 */
1237static void test_gmm_cancel(void)
1238{
1239 struct gprs_ra_id raid = { 0, };
1240 struct sgsn_mm_ctx *ctx = NULL;
1241 struct sgsn_mm_ctx *ictx;
1242 uint32_t ptmsi1;
1243 uint32_t foreign_tlli;
1244 uint32_t local_tlli = 0;
1245 struct gprs_llc_lle *lle;
1246 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1247
1248 /* DTAP - Attach Request */
1249 /* The P-TMSI is not known by the SGSN */
1250 static const unsigned char attach_req[] = {
1251 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1252 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1253 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1254 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1255 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1256 };
1257
1258 /* DTAP - Identity Response IMEI */
1259 static const unsigned char ident_resp_imei[] = {
1260 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1261 0x56
1262 };
1263
1264 /* DTAP - Identity Response IMSI */
1265 static const unsigned char ident_resp_imsi[] = {
1266 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1267 0x54
1268 };
1269
1270 /* DTAP - Attach Complete */
1271 static const unsigned char attach_compl[] = {
1272 0x08, 0x03
1273 };
1274
1275 printf("Testing cancellation\n");
1276
1277 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1278
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001279 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1280
1281 /* Create a LLE/LLME */
1282 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1283 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1284 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1285
1286 /* inject the attach request */
Jacob Erlbeck91580892016-01-04 18:43:33 +01001287 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001288 attach_req, ARRAY_SIZE(attach_req));
1289
1290 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1291 OSMO_ASSERT(ctx != NULL);
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001292 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001293
1294 /* we expect an identity request (IMEI) */
1295 OSMO_ASSERT(sgsn_tx_counter == 1);
1296
1297 /* inject the identity response (IMEI) */
Harald Weltef97ee042015-12-25 19:12:21 +01001298 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001299 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1300
1301 /* we expect an identity request (IMSI) */
1302 OSMO_ASSERT(sgsn_tx_counter == 1);
1303
1304 /* inject the identity response (IMSI) */
Harald Weltef97ee042015-12-25 19:12:21 +01001305 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001306 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1307
1308 /* check that the MM context has not been removed due to a failed
1309 * authorization */
1310 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1311
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001312 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001313
1314 /* we expect an attach accept/reject */
1315 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck133e8622015-10-12 19:36:32 +02001316 ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
1317 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001318
1319 /* this has been randomly assigned by the SGSN */
1320 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1321
1322 /* inject the attach complete */
Harald Weltef97ee042015-12-25 19:12:21 +01001323 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001324 attach_compl, ARRAY_SIZE(attach_compl));
1325
Pau Espin Pedrol31c46572019-09-02 16:45:27 +02001326 OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001327
1328 /* we don't expect a response */
1329 OSMO_ASSERT(sgsn_tx_counter == 0);
1330
1331 /* cancel */
Jacob Erlbeckaf3d5c52015-01-05 17:51:17 +01001332 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001333
1334 /* verify that things are gone */
1335 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1336 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1337 OSMO_ASSERT(!ictx);
1338
1339 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001340
1341 cleanup_test();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001342}
1343
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001344static void test_apn_matching(void)
1345{
1346 struct apn_ctx *actx, *actxs[9];
1347
1348 printf("Testing APN matching\n");
1349
1350 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1351 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1352 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1353 actxs[3] = NULL;
1354
1355 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1356 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1357 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1358 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1359
1360 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1361
1362 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1363 OSMO_ASSERT(actx == actxs[2]);
1364 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1365 OSMO_ASSERT(actx == actxs[2]);
1366 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1367 OSMO_ASSERT(actx == actxs[1]);
1368 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1369 OSMO_ASSERT(actx == actxs[1]);
1370 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1371 OSMO_ASSERT(actx == actxs[0]);
1372 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1373 OSMO_ASSERT(actx == NULL);
1374
1375 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1376 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1377 OSMO_ASSERT(actx == actxs[3]);
1378
1379 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1380 OSMO_ASSERT(actx == actxs[4]);
1381
1382 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1383 OSMO_ASSERT(actx == actxs[6]);
1384
1385 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1386 OSMO_ASSERT(actx == actxs[5]);
1387
1388 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1389 OSMO_ASSERT(actx == actxs[7]);
1390
1391 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1392 OSMO_ASSERT(actx == actxs[8]);
1393
1394 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1395 OSMO_ASSERT(actx == actxs[7]);
1396
1397 /* Free APN contexts and check how the matching changes */
1398
1399 sgsn_apn_ctx_free(actxs[7]);
1400 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1401 OSMO_ASSERT(actx == actxs[8]);
1402
1403 sgsn_apn_ctx_free(actxs[8]);
1404 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1405 OSMO_ASSERT(actx == actxs[6]);
1406
1407 sgsn_apn_ctx_free(actxs[6]);
1408 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1409 OSMO_ASSERT(actx == actxs[1]);
1410
1411 sgsn_apn_ctx_free(actxs[5]);
1412 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1413 OSMO_ASSERT(actx == actxs[4]);
1414
1415 sgsn_apn_ctx_free(actxs[4]);
1416 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1417 OSMO_ASSERT(actx == actxs[2]);
1418
1419 sgsn_apn_ctx_free(actxs[2]);
1420 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1421 OSMO_ASSERT(actx == actxs[1]);
1422
1423 sgsn_apn_ctx_free(actxs[1]);
1424 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1425 OSMO_ASSERT(actx == actxs[0]);
1426
1427 sgsn_apn_ctx_free(actxs[0]);
1428 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1429 OSMO_ASSERT(actx == actxs[3]);
1430
1431 sgsn_apn_ctx_free(actxs[3]);
1432 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1433 OSMO_ASSERT(actx == NULL);
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001434
1435 cleanup_test();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001436}
1437
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001438struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1439 struct sgsn_subscriber_data *sdata);
1440
1441static void test_ggsn_selection(void)
1442{
1443 struct apn_ctx *actxs[4];
1444 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001445 struct gprs_subscr *s1;
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001446 const char *imsi1 = "1234567890";
1447 struct sgsn_mm_ctx *ctx;
1448 struct gprs_ra_id raid = { 0, };
1449 uint32_t local_tlli = 0xffeeddcc;
1450 enum gsm48_gsm_cause gsm_cause;
1451 struct tlv_parsed tp;
1452 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1453 struct sgsn_subscriber_pdp_data *pdp_data;
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001454 char apn_str[GSM_APN_LENGTH];
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001455
1456 printf("Testing GGSN selection\n");
1457
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001458 osmo_gsup_client_send_cb = my_gsup_client_send_dummy;
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001459
1460 /* Check for emptiness */
1461 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1462
1463 /* Create a context */
1464 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1465 ctx = alloc_mm_ctx(local_tlli, &raid);
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001466 osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001467
1468 /* Allocate and attach a subscriber */
1469 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1470 assert_subscr(s1, imsi1);
1471
1472 tp.lv[GSM48_IE_GSM_APN].len = 0;
1473 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1474
1475 /* TODO: Add PDP info entries to s1 */
1476
1477 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1478 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1479 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1480
1481 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1482 actxs[0]->ggsn = ggcs[0];
1483 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1484 actxs[1]->ggsn = ggcs[1];
1485 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1486 actxs[2]->ggsn = ggcs[2];
1487
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001488 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1489 pdp_data->context_id = 1;
1490 pdp_data->pdp_type = 0x0121;
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001491 osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001492
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001493 /* Resolve GGSNs */
1494
1495 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001496 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001497
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001498 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001499 OSMO_ASSERT(ggc != NULL);
1500 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001501 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001502
1503 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001504 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001505
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001506 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001507 OSMO_ASSERT(ggc != NULL);
1508 OSMO_ASSERT(ggc->id == 1);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001509 OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001510
1511 tp.lv[GSM48_IE_GSM_APN].len = 0;
1512 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1513
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001514 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001515 OSMO_ASSERT(ggc != NULL);
1516 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001517 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001518
1519 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1520 actxs[3]->ggsn = ggcs[2];
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001521 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001522 OSMO_ASSERT(ggc != NULL);
1523 OSMO_ASSERT(ggc->id == 2);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001524 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001525
1526 sgsn_apn_ctx_free(actxs[3]);
1527 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1528
1529 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001530 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Foo.Bar");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001531
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001532 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001533 OSMO_ASSERT(ggc == NULL);
1534 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001535 OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001536
1537 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001538 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001539 OSMO_ASSERT(ggc == NULL);
1540 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1541
1542 /* Add PDP data entry to subscriber */
1543
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001544 osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001545
1546 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001547 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001548
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001549 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001550 OSMO_ASSERT(ggc != NULL);
1551 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001552 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001553
1554 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001555 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001556
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001557 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001558 OSMO_ASSERT(ggc == NULL);
1559 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001560 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001561
1562 /* Cleanup */
1563
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001564 gprs_subscr_put(s1);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001565 sgsn_mm_ctx_cleanup_free(ctx);
1566
1567 assert_no_subscrs();
1568
1569 sgsn_apn_ctx_free(actxs[0]);
1570 sgsn_apn_ctx_free(actxs[1]);
1571 sgsn_apn_ctx_free(actxs[2]);
1572
1573 sgsn_ggsn_ctx_free(ggcs[0]);
1574 sgsn_ggsn_ctx_free(ggcs[1]);
1575 sgsn_ggsn_ctx_free(ggcs[2]);
1576
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001577 osmo_gsup_client_send_cb = __real_osmo_gsup_client_send;
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001578
1579 cleanup_test();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001580}
1581
efistokldef0d942019-04-23 14:37:13 +03001582bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
1583
1584static void test_pdp_status_has_active_nsapis(void)
1585{
1586 const size_t pdp_status_len = 2;
1587 const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
1588 const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
1589 const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
1590
1591 printf("Testing pdp_status_has_active_nsapis\n");
1592
1593 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
1594 OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
1595 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
1596}
1597
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001598static struct log_info_cat gprs_categories[] = {
1599 [DMM] = {
1600 .name = "DMM",
1601 .description = "Layer3 Mobility Management (MM)",
1602 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001603 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001604 },
1605 [DPAG] = {
1606 .name = "DPAG",
1607 .description = "Paging Subsystem",
1608 .color = "\033[1;38m",
1609 .enabled = 1, .loglevel = LOGL_NOTICE,
1610 },
1611 [DMEAS] = {
1612 .name = "DMEAS",
1613 .description = "Radio Measurement Processing",
1614 .enabled = 0, .loglevel = LOGL_NOTICE,
1615 },
1616 [DREF] = {
1617 .name = "DREF",
1618 .description = "Reference Counting",
1619 .enabled = 0, .loglevel = LOGL_NOTICE,
1620 },
1621 [DGPRS] = {
1622 .name = "DGPRS",
1623 .description = "GPRS Packet Service",
1624 .enabled = 1, .loglevel = LOGL_DEBUG,
1625 },
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001626 [DLLC] = {
1627 .name = "DLLC",
1628 .description = "GPRS Logical Link Control Protocol (LLC)",
1629 .enabled = 1, .loglevel = LOGL_DEBUG,
1630 },
1631 [DSNDCP] = {
1632 .name = "DSNDCP",
1633 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1634 .enabled = 1, .loglevel = LOGL_DEBUG,
1635 },
1636};
1637
1638static struct log_info info = {
1639 .cat = gprs_categories,
1640 .num_cat = ARRAY_SIZE(gprs_categories),
1641};
1642
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001643static struct vty_app_info vty_info = {
1644 .name = "testSGSN",
1645};
1646
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001647int main(int argc, char **argv)
1648{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001649 void *osmo_sgsn_ctx;
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001650 void *msgb_ctx;
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001651
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001652 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
Neels Hofmeyr5bd340e2018-04-16 00:57:10 +02001653 osmo_init_logging2(osmo_sgsn_ctx, &info);
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +01001654 tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001655 msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001656
Alexander Couzens14314bd2016-07-05 09:52:52 +02001657 sgsn_rate_ctr_init();
Max2e485762018-12-10 18:01:47 +01001658 sgsn_auth_init(sgsn);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001659 gprs_subscr_init(sgsn);
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001660 vty_init(&vty_info);
1661 sgsn_vty_init(&sgsn->cfg);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001662
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001663 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001664 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001665 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001666 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001667 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001668 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001669 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001670 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001671 test_gmm_status_no_mmctx();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001672 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001673 test_gmm_cancel();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001674 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001675 test_ggsn_selection();
efistokldef0d942019-04-23 14:37:13 +03001676 test_pdp_status_has_active_nsapis();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001677 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001678
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001679 talloc_report_full(osmo_sgsn_ctx, stderr);
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001680 OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +01001681 OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 2);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001682 return 0;
1683}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001684
1685
1686/* stubs */
1687struct osmo_prim_hdr;
1688int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1689{
1690 abort();
1691}