blob: 7d3bde5765262fe39a6efa441391ac44956e88cd [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;
Pau Espin Pedrole659f752023-01-05 17:20:37 +010048struct sgsn_instance *sgsn;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010049unsigned sgsn_tx_counter = 0;
Jacob Erlbeck133e8622015-10-12 19:36:32 +020050struct msgb *last_msg = NULL;
51struct gprs_gb_parse_context last_dl_parse_ctx;
52
Pau Espin Pedrolf37aedb2023-01-05 14:20:27 +010053static void reset_last_msg(void)
Jacob Erlbeck133e8622015-10-12 19:36:32 +020054{
55 if (last_msg)
56 msgb_free(last_msg);
57
58 last_msg = NULL;
59 memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
60}
Jacob Erlbeck189999d2014-10-27 14:34:13 +010061
Pau Espin Pedrolf37aedb2023-01-05 14:20:27 +010062static void cleanup_test(void)
Jacob Erlbeckcf151872015-10-12 19:36:31 +020063{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020064 reset_last_msg();
Pau Espin Pedrole659f752023-01-05 17:20:37 +010065 TALLOC_FREE(sgsn);
Jacob Erlbeck133e8622015-10-12 19:36:32 +020066}
67
68static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
69{
70 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
71
72 if (parse_ctx->new_ptmsi_enc)
73 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
74
75 return new_ptmsi;
Jacob Erlbeckcf151872015-10-12 19:36:31 +020076}
77
Jacob Erlbeck189999d2014-10-27 14:34:13 +010078/* override */
79int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
80 struct bssgp_dl_ud_par *dup)
81{
Jacob Erlbeck133e8622015-10-12 19:36:32 +020082 int rc;
83
84 reset_last_msg();
85
86 last_msg = msg;
87 OSMO_ASSERT(msgb_data(last_msg) != NULL);
88
89 rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
90 &last_dl_parse_ctx);
91
92 fprintf(stderr, "Got DL LLC message: %s\n",
93 gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
94
95 OSMO_ASSERT(rc > 0);
96
Jacob Erlbeck189999d2014-10-27 14:34:13 +010097 sgsn_tx_counter += 1;
98 return 0;
99}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200100
Max3b6332f2017-11-01 13:28:38 +0100101/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
102int __real_osmo_get_rand_id(uint8_t *data, size_t len);
103int mock_osmo_get_rand_id(uint8_t *data, size_t len);
104int (*osmo_get_rand_id_cb)(uint8_t *, size_t) =
105 &mock_osmo_get_rand_id;
Max4011e722016-07-05 15:19:12 +0200106
Max3b6332f2017-11-01 13:28:38 +0100107int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200108{
Max3b6332f2017-11-01 13:28:38 +0100109 return (*osmo_get_rand_id_cb)(buf, num);
Max4011e722016-07-05 15:19:12 +0200110}
111/* make results of A&C ref predictable */
Max3b6332f2017-11-01 13:28:38 +0100112int mock_osmo_get_rand_id(uint8_t *buf, size_t num)
Max4011e722016-07-05 15:19:12 +0200113{
114 if (num > 1)
Max3b6332f2017-11-01 13:28:38 +0100115 return __real_osmo_get_rand_id(buf, num);
Max4011e722016-07-05 15:19:12 +0200116 buf[0] = 0;
117 return 1;
118}
119
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100120/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100121void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
122void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100123 &__real_sgsn_update_subscriber_data;
124
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100125void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100126{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100127 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100128}
129
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100130/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
131int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
132int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
133 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100134
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100135int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
136 return (*subscr_request_update_location_cb)(mmctx);
137};
138
139/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200140int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
141int (*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 +0100142 &__real_gprs_subscr_request_auth_info;
143
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200144int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
145 return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100146};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100147
Neels Hofmeyr814fef02016-12-08 21:19:57 +0100148/* override, requires '-Wl,--wrap=gsup_client_send' */
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200149int __real_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
150int (*osmo_gsup_client_send_cb)(struct osmo_gsup_client *gsupc, struct msgb *msg) =
151 &__real_osmo_gsup_client_send;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100152
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200153int __wrap_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100154{
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200155 return (*osmo_gsup_client_send_cb)(gsupc, msg);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100156};
157
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200158static int count(struct llist_head *head)
159{
160 struct llist_head *cur;
161 int count = 0;
162
163 llist_for_each(cur, head)
164 count += 1;
165
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100166 return count;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200167}
168
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200169static struct msgb *create_msg(const uint8_t *data, size_t len)
170{
171 struct msgb *msg = msgb_alloc(len + 8, "test message");
172 msg->l1h = msgb_put(msg, 8);
173 msg->l2h = msgb_put(msg, len);
174 memcpy(msg->l2h, data, len);
175
176 msgb_bcid(msg) = msg->l1h;
177 msgb_gmmh(msg) = msg->l2h;
178 return msg;
179}
180
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100181/*
182 * Create a context and search for it
183 */
184static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
185{
186 struct sgsn_mm_ctx *ctx, *ictx;
187 struct gprs_llc_lle *lle;
188 int old_count = count(gprs_llme_list());
189
190 lle = gprs_lle_get_or_create(tlli, 3);
Alexander Couzens2b5fb8e2017-02-04 06:01:00 +0100191 ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
Harald Weltef97ee042015-12-25 19:12:21 +0100192 ctx->gb.llme = lle->llme;
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100193
194 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
195 OSMO_ASSERT(ictx == ctx);
196
197 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
198
199 return ctx;
200}
201
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100202static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
Jacob Erlbeck91580892016-01-04 18:43:33 +0100203 const struct gprs_ra_id *bssgp_raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100204 const uint8_t *data, size_t data_len)
205{
206 struct msgb *msg;
207
Jacob Erlbeck133e8622015-10-12 19:36:32 +0200208 reset_last_msg();
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100209 sgsn_tx_counter = 0;
210
211 msg = create_msg(data, data_len);
212 msgb_tlli(msg) = tlli;
Jacob Erlbeck91580892016-01-04 18:43:33 +0100213 bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
Max82040102016-07-06 11:59:18 +0200214 gsm0408_gprs_rcvmsg_gb(msg, llme, false);
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100215 msgb_free(msg);
216}
217
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200218static void test_llme(void)
219{
220 struct gprs_llc_lle *lle, *lle_copy;
221 uint32_t local_tlli;
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200222
223 printf("Testing LLME allocations\n");
224 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200225
226 /* initial state */
227 OSMO_ASSERT(count(gprs_llme_list()) == 0);
228
229 /* Create a new entry */
230 lle = gprs_lle_get_or_create(local_tlli, 3);
231 OSMO_ASSERT(lle);
232 OSMO_ASSERT(count(gprs_llme_list()) == 1);
233
234 /* No new entry is created */
235 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
236 OSMO_ASSERT(lle == lle_copy);
237 OSMO_ASSERT(count(gprs_llme_list()) == 1);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200238
239 /* unassign which should delete it*/
Max39550252016-06-28 17:39:20 +0200240 gprs_llgmm_unassign(lle->llme);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200241
242 /* Check that everything was cleaned up */
243 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200244
245 cleanup_test();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200246}
247
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100248struct gprs_subscr *last_updated_subscr = NULL;
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100249void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100250{
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100251 OSMO_ASSERT(mmctx);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100252 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100253 __func__, mmctx, mmctx->subscr);
254 last_updated_subscr = mmctx->subscr;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100255}
256
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100257static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100258{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100259 struct gprs_subscr *sfound;
Jacob Erlbeck6be9ffa2015-01-19 08:57:07 +0100260 OSMO_ASSERT(subscr);
261 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100262
263 sfound = gprs_subscr_get_by_imsi(imsi);
264 OSMO_ASSERT(sfound == subscr);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100265
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100266 gprs_subscr_put(sfound);
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100267}
268
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100269static void show_subscrs(FILE *out)
270{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100271 struct gprs_subscr *subscr;
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100272
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100273 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100274 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100275 "use count: %d\n",
276 subscr->imsi, subscr->use_count);
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100277 }
278}
279
Pau Espin Pedrolf37aedb2023-01-05 14:20:27 +0100280static void assert_no_subscrs(void)
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100281{
282 show_subscrs(stdout);
283 fflush(stdout);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100284 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck058bc262015-01-13 11:46:32 +0100285}
286
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100287#define VERBOSE_ASSERT(val, expect_op, fmt) \
288 do { \
289 printf(#val " == " fmt "\n", (val)); \
290 OSMO_ASSERT((val) expect_op); \
291 } while (0);
292
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100293static void test_subscriber(void)
294{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100295 struct gprs_subscr *s1, *s2, *s3;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100296 const char *imsi1 = "1234567890";
297 const char *imsi2 = "9876543210";
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100298 const char *imsi3 = "5656565656";
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100299
300 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
301
302 printf("Testing core subscriber data API\n");
303
304 /* Check for emptiness */
305 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
306 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100307 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100308 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100309
310 /* Allocate entry 1 */
311 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100312 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
313 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100314 assert_subscr(s1, imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100315 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100316 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100317
318 /* Allocate entry 2 */
319 s2 = gprs_subscr_get_or_create(imsi2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100320 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
321 s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100322
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100323 /* Allocate entry 3 */
324 s3 = gprs_subscr_get_or_create(imsi3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100325 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100326
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100327 /* Check entries */
328 assert_subscr(s1, imsi1);
329 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100330 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100331
332 /* Update entry 1 */
333 last_updated_subscr = NULL;
334 gprs_subscr_update(s1);
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100335 OSMO_ASSERT(last_updated_subscr == NULL);
336 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100337 OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100338
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100339 /* There is no subscriber cache. Verify it */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100340 gprs_subscr_cleanup(s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100341 gprs_subscr_put(s1);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100342 s1 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100343 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
344 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100345
Jacob Erlbeckb8fb1402015-01-09 11:59:50 +0100346 assert_subscr(s2, imsi2);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100347 assert_subscr(s3, imsi3);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100348
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100349 /* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100350 gprs_subscr_cleanup(s2);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100351 gprs_subscr_put(s2);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100352 s2 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100353 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100354 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
355 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100356 assert_subscr(s3, imsi3);
357
358 /* Try to delete entry 3 */
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100359 gprs_subscr_cleanup(s3);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100360 gprs_subscr_put(s3);
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100361 s3 = NULL;
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100362 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100363 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100364
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100365 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100366
367 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200368
369 cleanup_test();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100370}
371
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100372static void test_auth_triplets(void)
373{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100374 struct gprs_subscr *s1, *s1found;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100375 const char *imsi1 = "1234567890";
376 struct gsm_auth_tuple *at;
377 struct sgsn_mm_ctx *ctx;
378 struct gprs_ra_id raid = { 0, };
379 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100380
381 printf("Testing authentication triplet handling\n");
382
383 /* Check for emptiness */
384 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
385
386 /* Allocate entry 1 */
387 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100388 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100389 s1found = gprs_subscr_get_by_imsi(imsi1);
390 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100391 gprs_subscr_put(s1found);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100392
393 /* Create a context */
394 OSMO_ASSERT(count(gprs_llme_list()) == 0);
395 ctx = alloc_mm_ctx(local_tlli, &raid);
396
397 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100398 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100399 ctx->subscr->sgsn_data->mm = ctx;
400
401 /* Try to get auth tuple */
402 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
403 OSMO_ASSERT(at == NULL);
404
405 /* Add triplets */
406 s1->sgsn_data->auth_triplets[0].key_seq = 0;
407 s1->sgsn_data->auth_triplets[1].key_seq = 1;
408 s1->sgsn_data->auth_triplets[2].key_seq = 2;
409
410 /* Try to get auth tuple */
411 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
412 OSMO_ASSERT(at != NULL);
413 OSMO_ASSERT(at->key_seq == 0);
414 OSMO_ASSERT(at->use_count == 1);
415 at = sgsn_auth_get_tuple(ctx, at->key_seq);
416 OSMO_ASSERT(at != NULL);
417 OSMO_ASSERT(at->key_seq == 1);
418 OSMO_ASSERT(at->use_count == 1);
419 at = sgsn_auth_get_tuple(ctx, at->key_seq);
420 OSMO_ASSERT(at != NULL);
421 OSMO_ASSERT(at->key_seq == 2);
422 OSMO_ASSERT(at->use_count == 1);
423 at = sgsn_auth_get_tuple(ctx, at->key_seq);
424 OSMO_ASSERT(at == NULL);
425
426 /* Free MM context and subscriber */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100427 gprs_subscr_put(s1);
Jacob Erlbecke671d252015-01-26 14:43:07 +0100428 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100429 s1found = gprs_subscr_get_by_imsi(imsi1);
430 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200431
432 cleanup_test();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100433}
434
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100435#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
436
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100437static int rx_gsup_message(const uint8_t *data, size_t data_len)
438{
439 struct msgb *msg;
440 int rc;
441
442 msg = msgb_alloc(1024, __func__);
443 msg->l2h = msgb_put(msg, data_len);
444 OSMO_ASSERT(msg->l2h != NULL);
445 memcpy(msg->l2h, data, data_len);
446 rc = gprs_subscr_rx_gsup_message(msg);
447 msgb_free(msg);
448
449 return rc;
450}
451
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100452static void test_subscriber_gsup(void)
453{
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100454 struct gprs_subscr *s1, *s1found;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100455 const char *imsi1 = "1234567890";
456 struct sgsn_mm_ctx *ctx;
457 struct gprs_ra_id raid = { 0, };
458 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100459 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100460 int rc;
461
462 static const uint8_t send_auth_info_res[] = {
463 0x0a,
464 TEST_GSUP_IMSI1_IE,
465 0x03, 0x22, /* Auth tuple */
466 0x20, 0x10,
467 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
468 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
469 0x21, 0x04,
470 0x21, 0x22, 0x23, 0x24,
471 0x22, 0x08,
472 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
473 0x03, 0x22, /* Auth tuple */
474 0x20, 0x10,
475 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
476 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
477 0x21, 0x04,
478 0xa1, 0xa2, 0xa3, 0xa4,
479 0x22, 0x08,
480 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
481 };
482
483 static const uint8_t send_auth_info_err[] = {
484 0x09,
485 TEST_GSUP_IMSI1_IE,
486 0x02, 0x01, 0x07 /* GPRS not allowed */
487 };
488
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400489#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
490
491 static const uint8_t s1_msisdn[] = { MSISDN };
492
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100493 static const uint8_t update_location_res[] = {
494 0x06,
495 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400496 0x08, 0x09, MSISDN,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100497 0x04, 0x00, /* PDP info complete */
498 0x05, 0x12,
499 0x10, 0x01, 0x01,
500 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
501 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
502 0x05, 0x11,
503 0x10, 0x01, 0x02,
504 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
505 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
506 };
507
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400508#undef MSISDN
509
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100510 static const uint8_t update_location_err[] = {
511 0x05,
512 TEST_GSUP_IMSI1_IE,
513 0x02, 0x01, 0x07 /* GPRS not allowed */
514 };
515
516 static const uint8_t location_cancellation_req[] = {
517 0x1c,
518 TEST_GSUP_IMSI1_IE,
519 0x06, 0x01, 0x00,
520 };
521
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200522 static const uint8_t location_cancellation_req_withdraw[] = {
523 0x1c,
524 TEST_GSUP_IMSI1_IE,
525 0x06, 0x01, 0x01,
526 };
527
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100528 static const uint8_t location_cancellation_req_other[] = {
529 0x1c,
530 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
531 0x06, 0x01, 0x00,
532 };
533
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100534 static const uint8_t purge_ms_err[] = {
535 0x0d,
536 TEST_GSUP_IMSI1_IE,
537 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
538 };
539
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100540 static const uint8_t purge_ms_err_no_cause[] = {
541 0x0d,
542 TEST_GSUP_IMSI1_IE,
543 };
544
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100545 static const uint8_t purge_ms_res[] = {
546 0x0e,
547 TEST_GSUP_IMSI1_IE,
548 0x07, 0x00,
549 };
550
551
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100552 static const uint8_t insert_data_req[] = {
553 0x10,
554 TEST_GSUP_IMSI1_IE,
555 0x05, 0x11,
556 0x10, 0x01, 0x03,
557 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
558 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
559 };
560
561 static const uint8_t delete_data_req[] = {
562 0x14,
563 TEST_GSUP_IMSI1_IE,
564 0x10, 0x01, 0x03,
565 };
566
Neels Hofmeyr241bda02016-06-20 18:26:15 +0200567 printf("Testing subscriber GSUP handling\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100568
569 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
Pau Espin Pedrole659f752023-01-05 17:20:37 +0100570 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100571
572 /* Check for emptiness */
573 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
574
575 /* Allocate entry 1 */
576 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100577 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100578 s1found = gprs_subscr_get_by_imsi(imsi1);
579 OSMO_ASSERT(s1found == s1);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100580 gprs_subscr_put(s1found);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100581
582 /* Create a context */
583 OSMO_ASSERT(count(gprs_llme_list()) == 0);
584 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100585
586 /* Attach s1 to ctx */
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100587 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100588 ctx->subscr->sgsn_data->mm = ctx;
589
590 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100591 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100592 OSMO_ASSERT(rc >= 0);
593 OSMO_ASSERT(last_updated_subscr == s1);
594
595 /* Check triplets */
596 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
597 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
598 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
599
600 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100601 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100602 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100603 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100604 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100605
606 /* Check triplets */
607 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
608 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
609 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
610
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100611 /* Inject UpdateLocRes GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100612 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100613 OSMO_ASSERT(rc >= 0);
614 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100615 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100616 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther9ba273d2015-04-23 09:53:53 -0400617 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
618 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck0e8add62014-12-17 14:03:35 +0100619 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
620 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
621 struct sgsn_subscriber_pdp_data, list);
622 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
623 pdpd = llist_entry(pdpd->list.next,
624 struct sgsn_subscriber_pdp_data, list);
625 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100626
627 /* Check authorization */
628 OSMO_ASSERT(s1->authorized == 1);
629
630 /* Inject UpdateLocErr GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100631 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100632 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100633 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100634 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100635
636 /* Check authorization */
637 OSMO_ASSERT(s1->authorized == 0);
638
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100639 /* Inject InsertSubscrData GSUP message */
640 last_updated_subscr = NULL;
641 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Harald Weltec346f872016-11-26 14:58:36 +0100642 OSMO_ASSERT(rc == -ENOTSUP); /* not connected */
Harald Weltecd5e5262016-05-06 13:46:21 +0200643 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100644
645 /* Inject DeleteSubscrData GSUP message */
646 last_updated_subscr = NULL;
647 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
Maxa66d8cf2017-02-15 11:43:59 +0100648 if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
649 printf("Unexpected response to DSD: %d\n", rc);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100650 OSMO_ASSERT(last_updated_subscr == NULL);
651
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100652 /* Inject wrong LocCancelReq GSUP message */
653 last_updated_subscr = NULL;
654 rc = rx_gsup_message(location_cancellation_req_other,
655 sizeof(location_cancellation_req_other));
656 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
657 OSMO_ASSERT(last_updated_subscr == NULL);
658
659 /* Check cancellation result */
660 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
661 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
662
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100663 /* Inject LocCancelReq GSUP message */
Jacob Erlbecke21e1842014-12-19 18:19:50 +0100664 rc = rx_gsup_message(location_cancellation_req,
665 sizeof(location_cancellation_req));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100666 OSMO_ASSERT(rc >= 0);
667 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeckbaf0f942015-01-29 14:55:34 +0100668 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100669
670 /* Check cancellation result */
671 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
672 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
673
Jacob Erlbeck5b512052015-04-07 17:49:48 +0200674 /* Inject LocCancelReq(withdraw) GSUP message */
675 rc = rx_gsup_message(location_cancellation_req_withdraw,
676 sizeof(location_cancellation_req_withdraw));
677 OSMO_ASSERT(rc >= 0);
678 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
679
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100680 /* Inject PurgeMsRes GSUP message */
681 rc = rx_gsup_message(purge_ms_res,
682 sizeof(purge_ms_res));
683 OSMO_ASSERT(rc >= 0);
684 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
685
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100686 /* Free MM context and subscriber */
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +0100687 OSMO_ASSERT(ctx->subscr == NULL);
688 sgsn_mm_ctx_cleanup_free(ctx);
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +0100689 gprs_subscr_put(s1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100690 s1found = gprs_subscr_get_by_imsi(imsi1);
691 OSMO_ASSERT(s1found == NULL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100692
Jacob Erlbeck466cedd2015-01-29 14:12:29 +0100693 /* Inject PurgeMsRes GSUP message */
694 rc = rx_gsup_message(purge_ms_res,
695 sizeof(purge_ms_res));
696 OSMO_ASSERT(rc >= 0);
697
698 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
699 rc = rx_gsup_message(purge_ms_err,
700 sizeof(purge_ms_err));
701 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
702
Jacob Erlbeck9ff82892015-01-29 14:17:51 +0100703 /* Inject PurgeMsErr() GSUP message */
704 rc = rx_gsup_message(purge_ms_err_no_cause,
705 sizeof(purge_ms_err_no_cause));
706 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
707
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100708 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
709 last_updated_subscr = NULL;
710 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100711 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100712 OSMO_ASSERT(last_updated_subscr == NULL);
713
714 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
715 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
716 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
717 OSMO_ASSERT(last_updated_subscr == NULL);
718
719 /* Inject LocCancelReq GSUP message (unknown IMSI) */
720 rc = rx_gsup_message(location_cancellation_req,
721 sizeof(location_cancellation_req));
722 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
723 OSMO_ASSERT(last_updated_subscr == NULL);
724
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100725 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200726
727 cleanup_test();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100728}
729
Harald Weltef4b2c4c2018-09-16 07:53:41 +0200730int my_gsup_client_send_dummy(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100731{
732 msgb_free(msg);
733 return 0;
734};
735
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200736/*
737 * Test that a GMM Detach will remove the MMCTX and the
738 * associated LLME.
739 */
740static void test_gmm_detach(void)
741{
742 struct gprs_ra_id raid = { 0, };
743 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200744 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200745
746 printf("Testing GMM detach\n");
Pau Espin Pedrole659f752023-01-05 17:20:37 +0100747 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200748
749 /* DTAP - Detach Request (MO) */
750 /* normal detach, power_off = 0 */
751 static const unsigned char detach_req[] = {
752 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
753 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
754 };
755
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200756 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200757
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100758 /* Create a context */
759 OSMO_ASSERT(count(gprs_llme_list()) == 0);
760 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200761
762 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100763 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100764 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200765
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100766 /* verify that a single message (hopefully the Detach Accept) has been
767 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100768 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100769
770 /* verify that things are gone */
771 OSMO_ASSERT(count(gprs_llme_list()) == 0);
772 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
773 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200774
775 cleanup_test();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100776}
777
778/*
779 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
780 * will not sent a Detach Accept message (power_off = 1)
781 */
782static void test_gmm_detach_power_off(void)
783{
784 struct gprs_ra_id raid = { 0, };
785 struct sgsn_mm_ctx *ctx, *ictx;
786 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100787
788 printf("Testing GMM detach (power off)\n");
Pau Espin Pedrole659f752023-01-05 17:20:37 +0100789 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100790
791 /* DTAP - Detach Request (MO) */
792 /* normal detach, power_off = 1 */
793 static const unsigned char detach_req[] = {
794 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
795 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
796 };
797
798 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
799
800 /* Create a context */
801 OSMO_ASSERT(count(gprs_llme_list()) == 0);
802 ctx = alloc_mm_ctx(local_tlli, &raid);
803
804 /* inject the detach */
Harald Weltef97ee042015-12-25 19:12:21 +0100805 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100806 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100807
808 /* verify that no message (and therefore no Detach Accept) has been
809 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100810 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100811
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200812 /* verify that things are gone */
813 OSMO_ASSERT(count(gprs_llme_list()) == 0);
814 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200815 OSMO_ASSERT(!ictx);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200816
817 cleanup_test();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200818}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200819
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200820/*
821 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
822 */
823static void test_gmm_detach_no_mmctx(void)
824{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100825 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200826 struct gprs_llc_lle *lle;
827 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200828
829 printf("Testing GMM detach (no MMCTX)\n");
Pau Espin Pedrole659f752023-01-05 17:20:37 +0100830 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200831
832 /* DTAP - Detach Request (MO) */
833 /* normal detach, power_off = 0 */
834 static const unsigned char detach_req[] = {
835 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
836 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
837 };
838
839 /* Create an LLME */
840 OSMO_ASSERT(count(gprs_llme_list()) == 0);
841 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
842 lle = gprs_lle_get_or_create(local_tlli, 3);
843
844 OSMO_ASSERT(count(gprs_llme_list()) == 1);
845
846 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100847 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100848 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200849
850 /* verify that the LLME is gone */
851 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200852
853 cleanup_test();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200854}
855
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100856/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100857 * Test that a single GMM Detach Accept message will not cause the SGSN to send
858 * any message or leave an MM context at the SGSN.
859 */
860static void test_gmm_detach_accept_unexpected(void)
861{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100862 struct gprs_ra_id raid = { 0, };
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100863 struct gprs_llc_lle *lle;
864 uint32_t local_tlli;
865
866 printf("Testing GMM detach accept (unexpected)\n");
867
868 /* DTAP - Detach Accept (MT) */
869 /* normal detach */
870 static const unsigned char detach_acc[] = {
871 0x08, 0x06
872 };
873
874 /* Create an LLME */
875 OSMO_ASSERT(count(gprs_llme_list()) == 0);
876 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
877 lle = gprs_lle_get_or_create(local_tlli, 3);
878
879 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100880 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100881 detach_acc, ARRAY_SIZE(detach_acc));
882
883 /* verify that no message (and therefore no Status or XID reset) has been
884 * sent by the SGSN */
885 OSMO_ASSERT(sgsn_tx_counter == 0);
886
887 /* verify that things are gone */
888 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200889
890 cleanup_test();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100891}
892
893/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100894 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
895 */
896static void test_gmm_status_no_mmctx(void)
897{
Jacob Erlbeck91580892016-01-04 18:43:33 +0100898 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100899 struct gprs_llc_lle *lle;
900 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100901
902 printf("Testing GMM Status (no MMCTX)\n");
903
904 /* DTAP - GMM Status, protocol error */
905 static const unsigned char gmm_status[] = {
906 0x08, 0x20, 0x6f
907 };
908
909 /* Create an LLME */
910 OSMO_ASSERT(count(gprs_llme_list()) == 0);
911 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
912 lle = gprs_lle_get_or_create(local_tlli, 3);
913
914 OSMO_ASSERT(count(gprs_llme_list()) == 1);
915
916 /* inject the detach */
Jacob Erlbeck91580892016-01-04 18:43:33 +0100917 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100918 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100919
920 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100921 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100922
923 /* verify that the LLME is gone */
924 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeckcf151872015-10-12 19:36:31 +0200925
926 cleanup_test();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100927}
928
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100929int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
930{
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100931 int rc;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100932 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100933 if (rc == -ENOTSUP) {
934 OSMO_ASSERT(mmctx->subscr);
935 gprs_subscr_update(mmctx->subscr);
936 }
937 return rc;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100938}
Jacob Erlbeckbe2c8d92014-11-12 10:18:09 +0100939
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100940int my_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
941 const uint8_t *auts_rand)
942{
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100943 gprs_subscr_update(mmctx->subscr);
944 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100945}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100946
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100947int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
948 const uint8_t *auts_rand)
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100949{
950 /* Fake an authentication */
951 OSMO_ASSERT(mmctx->subscr);
Neels Hofmeyraa4ed672018-04-22 19:29:41 +0200952 mmctx->sec_ctx = OSMO_AUTH_TYPE_GSM;
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100953 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100954
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100955 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100956}
Jacob Erlbeck2e5e94c2014-12-08 15:26:47 +0100957
Pau Espin Pedrol93fd4622017-08-16 11:30:01 +0200958int 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 +0100959{
960 struct gsm_auth_tuple at = {
Harald Welte121e9a42016-04-20 13:13:19 +0200961 .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
Neels Hofmeyr058cd572017-02-24 06:24:45 +0100962 .vec.auth_types = OSMO_AUTH_TYPE_GSM,
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100963 .key_seq = 0
964 };
965
966 /* Fake an authentication */
967 OSMO_ASSERT(mmctx->subscr);
968 mmctx->subscr->sgsn_data->auth_triplets[0] = at;
969
970 gprs_subscr_update_auth_info(mmctx->subscr);
971
972 return 0;
Pau Espin Pedrol76d2c8b2018-01-07 18:07:17 +0100973}
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100974
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100975#define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \
976 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
977
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100978static int auth_info_skip = 0;
979static int upd_loc_skip = 0;
980
Pau Espin Pedrol0b050392018-01-07 18:05:22 +0100981int my_subscr_request_auth_info_gsup_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts,
982 const uint8_t *auts_rand)
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100983{
984 static const uint8_t send_auth_info_res[] = {
985 0x0a,
986 TEST_GSUP_IMSI_LONG_IE,
987 0x03, 0x22, /* Auth tuple */
988 0x20, 0x10,
989 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
990 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
991 0x21, 0x04,
992 0x51, 0xe5, 0x51, 0xe5,
993 0x22, 0x08,
994 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
995 };
996
Jacob Erlbeckc157ee72015-01-09 15:07:16 +0100997 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +0100998
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +0100999 if (auth_info_skip > 0) {
1000 auth_info_skip -= 1;
1001 return -EAGAIN;
1002 }
1003
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001004 /* Fake an SendAuthInfoRes */
1005 rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
1006
1007 return 0;
1008};
1009
1010int my_subscr_request_update_gsup_auth(struct sgsn_mm_ctx *mmctx) {
1011 static const uint8_t update_location_res[] = {
1012 0x06,
1013 TEST_GSUP_IMSI_LONG_IE,
1014 0x04, 0x00, /* PDP info complete */
1015 0x05, 0x12,
1016 0x10, 0x01, 0x01,
1017 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
1018 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
Holger Hans Peter Freyther20de3ae2015-05-05 22:52:40 +02001019 0x08, 0x07, /* MSISDN 49166213323 encoded */
1020 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freyther10c0f562015-05-17 20:58:40 +02001021 0x09, 0x07, /* MSISDN 38166213323 encoded */
1022 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001023 };
1024
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001025 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001026
Jacob Erlbeck7660ffa2014-12-19 18:30:41 +01001027 if (upd_loc_skip > 0) {
1028 upd_loc_skip -= 1;
1029 return -EAGAIN;
1030 }
1031
Jacob Erlbeck3d722452014-12-19 18:26:09 +01001032 /* Fake an UpdateLocRes */
1033 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1034};
1035
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001036int my_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001037{
Harald Welte23d77d52016-04-25 19:07:34 +02001038 struct osmo_gsup_message to_peer = {0};
1039 struct osmo_gsup_message from_peer = {0};
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001040 struct msgb *reply_msg;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001041 int rc;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001042
1043 /* Simulate the GSUP peer */
Harald Welte23d77d52016-04-25 19:07:34 +02001044 rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001045 OSMO_ASSERT(rc >= 0);
1046 OSMO_ASSERT(to_peer.imsi[0] != 0);
Neels Hofmeyr59504dc2017-01-13 03:10:54 +01001047 osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001048
1049 /* This invalidates the pointers in to_peer */
1050 msgb_free(msg);
1051
1052 switch (to_peer.message_type) {
Harald Welte23d77d52016-04-25 19:07:34 +02001053 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001054 /* Send UPDATE_LOCATION_RESULT */
1055 return my_subscr_request_update_gsup_auth(NULL);
1056
Harald Welte23d77d52016-04-25 19:07:34 +02001057 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001058 /* Send SEND_AUTH_INFO_RESULT */
Pau Espin Pedrol0b050392018-01-07 18:05:22 +01001059 return my_subscr_request_auth_info_gsup_auth(NULL, NULL, NULL);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001060
Harald Welte23d77d52016-04-25 19:07:34 +02001061 case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
1062 from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001063 break;
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001064
1065 default:
1066 if ((to_peer.message_type & 0b00000011) == 0) {
1067 /* Unhandled request */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +01001068 /* Send error(NOT_IMPL) */
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001069 from_peer.message_type = to_peer.message_type + 1;
1070 from_peer.cause = GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
1071 break;
1072 }
1073
1074 /* Ignore it */
1075 return 0;
1076 }
1077
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001078 reply_msg = osmo_gsup_client_msgb_alloc();
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001079 reply_msg->l2h = reply_msg->data;
Harald Welte23d77d52016-04-25 19:07:34 +02001080 osmo_gsup_encode(reply_msg, &from_peer);
Jacob Erlbeckc157ee72015-01-09 15:07:16 +01001081 gprs_subscr_rx_gsup_message(reply_msg);
1082 msgb_free(reply_msg);
1083
1084 return 0;
1085};
1086
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001087/*
1088 * Test the GMM Rejects
1089 */
1090static void test_gmm_reject(void)
1091{
1092 struct gprs_ra_id raid = { 0, };
1093 struct sgsn_mm_ctx *ctx = NULL;
1094 uint32_t foreign_tlli;
1095 struct gprs_llc_lle *lle;
1096 int idx;
1097
1098 /* DTAP - Attach Request */
1099 /* Invalid MI length */
1100 static const unsigned char attach_req_inv_mi_len[] = {
1101 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
1102 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
1103 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
1104 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
1105 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1106 };
1107
1108 /* DTAP - Attach Request */
1109 /* Invalid MI type (IMEI) */
1110 static const unsigned char attach_req_inv_mi_type[] = {
1111 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
1112 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1113 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1114 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1115 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1116 };
1117
1118 /* DTAP - Routing Area Update Request */
1119 static const unsigned char dtap_ra_upd_req[] = {
1120 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1121 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1122 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1123 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1124 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1125 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1126 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1127 };
1128
1129 /* DTAP - Routing Area Update Request */
1130 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
1131 static const unsigned char dtap_ra_upd_req_inv_type[] = {
1132 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
1133 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1134 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1135 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1136 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1137 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1138 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1139 };
1140
1141 /* DTAP - Routing Area Update Request */
1142 /* Invalid cap length */
1143 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
1144 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
1145 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
1146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1148 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
1149 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
1150 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
1151 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
1152 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
1153 };
1154
1155 struct test {
1156 const char *title;
1157 const unsigned char *msg;
1158 unsigned msg_len;
1159 unsigned num_resp;
1160
1161 };
1162 static struct test tests[] = {
1163 {
1164 .title = "Attach Request (invalid MI length)",
1165 .msg = attach_req_inv_mi_len,
1166 .msg_len = sizeof(attach_req_inv_mi_len),
1167 .num_resp = 1 /* Reject */
1168
1169 },
1170 {
1171 .title = "Attach Request (invalid MI type)",
1172 .msg = attach_req_inv_mi_type,
1173 .msg_len = sizeof(attach_req_inv_mi_type),
1174 .num_resp = 1 /* Reject */
1175 },
1176 {
1177 .title = "Routing Area Update Request (valid)",
1178 .msg = dtap_ra_upd_req,
1179 .msg_len = sizeof(dtap_ra_upd_req),
1180 .num_resp = 2 /* XID Reset + Reject */
1181 },
1182 {
1183 .title = "Routing Area Update Request (invalid type)",
1184 .msg = dtap_ra_upd_req_inv_type,
1185 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
1186 .num_resp = 1 /* Reject */
1187 },
1188 {
1189 .title = "Routing Area Update Request (invalid CAP length)",
1190 .msg = dtap_ra_upd_req_inv_cap_len,
1191 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
1192 .num_resp = 1 /* Reject */
1193 },
1194 };
1195
1196 printf("Testing GMM reject\n");
Pau Espin Pedrole659f752023-01-05 17:20:37 +01001197 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001198
1199 /* reset the PRNG used by sgsn_alloc_ptmsi */
1200 srand(1);
1201
1202 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1203
1204 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1205
1206 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1207 const struct test *test = &tests[idx];
1208 printf(" - %s\n", test->title);
1209
1210 /* Create a LLE/LLME */
1211 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1212 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1213
1214 /* Inject the Request message */
Jacob Erlbeck91580892016-01-04 18:43:33 +01001215 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001216 test->msg, test->msg_len);
1217
1218 /* We expect a Reject message */
1219 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1220 sgsn_tx_counter, test->num_resp);
1221 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1222
1223 /* verify that LLME/MM are removed */
1224 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1225 OSMO_ASSERT(ctx == NULL);
1226 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1227 }
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001228
1229 cleanup_test();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001230}
1231
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +01001232/*
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001233 * Test cancellation of attached MM contexts
1234 */
1235static void test_gmm_cancel(void)
1236{
1237 struct gprs_ra_id raid = { 0, };
1238 struct sgsn_mm_ctx *ctx = NULL;
1239 struct sgsn_mm_ctx *ictx;
1240 uint32_t ptmsi1;
1241 uint32_t foreign_tlli;
1242 uint32_t local_tlli = 0;
1243 struct gprs_llc_lle *lle;
Pau Espin Pedrole659f752023-01-05 17:20:37 +01001244
1245 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
1246 sgsn->cfg.gea_encryption_mask = 0x1;
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001247 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1248
1249 /* DTAP - Attach Request */
1250 /* The P-TMSI is not known by the SGSN */
1251 static const unsigned char attach_req[] = {
1252 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1253 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1254 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1255 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1256 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1257 };
1258
1259 /* DTAP - Identity Response IMEI */
1260 static const unsigned char ident_resp_imei[] = {
1261 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1262 0x56
1263 };
1264
1265 /* DTAP - Identity Response IMSI */
1266 static const unsigned char ident_resp_imsi[] = {
1267 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1268 0x54
1269 };
1270
1271 /* DTAP - Attach Complete */
1272 static const unsigned char attach_compl[] = {
1273 0x08, 0x03
1274 };
1275
1276 printf("Testing cancellation\n");
Pau Espin Pedrole659f752023-01-05 17:20:37 +01001277 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001278
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;
Pau Espin Pedrole659f752023-01-05 17:20:37 +01001459 sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001460
1461 /* Check for emptiness */
1462 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1463
1464 /* Create a context */
1465 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1466 ctx = alloc_mm_ctx(local_tlli, &raid);
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001467 osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001468
1469 /* Allocate and attach a subscriber */
1470 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1471 assert_subscr(s1, imsi1);
1472
1473 tp.lv[GSM48_IE_GSM_APN].len = 0;
1474 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1475
1476 /* TODO: Add PDP info entries to s1 */
1477
1478 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1479 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1480 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1481
1482 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1483 actxs[0]->ggsn = ggcs[0];
1484 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1485 actxs[1]->ggsn = ggcs[1];
1486 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1487 actxs[2]->ggsn = ggcs[2];
1488
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001489 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1490 pdp_data->context_id = 1;
1491 pdp_data->pdp_type = 0x0121;
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001492 osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
Holger Hans Peter Freyther9270d992015-05-24 20:51:17 +08001493
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001494 /* Resolve GGSNs */
1495
1496 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001497 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001498
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001499 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001500 OSMO_ASSERT(ggc != NULL);
1501 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001502 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001503
1504 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001505 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001506
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001507 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001508 OSMO_ASSERT(ggc != NULL);
1509 OSMO_ASSERT(ggc->id == 1);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001510 OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001511
1512 tp.lv[GSM48_IE_GSM_APN].len = 0;
1513 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1514
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001515 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001516 OSMO_ASSERT(ggc != NULL);
1517 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001518 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001519
1520 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1521 actxs[3]->ggsn = ggcs[2];
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001522 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001523 OSMO_ASSERT(ggc != NULL);
1524 OSMO_ASSERT(ggc->id == 2);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001525 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001526
1527 sgsn_apn_ctx_free(actxs[3]);
1528 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1529
1530 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001531 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Foo.Bar");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001532
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001533 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001534 OSMO_ASSERT(ggc == NULL);
1535 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001536 OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001537
1538 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001539 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001540 OSMO_ASSERT(ggc == NULL);
1541 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1542
1543 /* Add PDP data entry to subscriber */
1544
Neels Hofmeyr93bafb62017-01-13 03:12:08 +01001545 osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001546
1547 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001548 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001549
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001550 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001551 OSMO_ASSERT(ggc != NULL);
1552 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001553 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001554
1555 tp.lv[GSM48_IE_GSM_APN].len =
Pau Espin Pedrolfc1a5532023-01-04 16:34:16 +01001556 osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001557
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001558 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001559 OSMO_ASSERT(ggc == NULL);
1560 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
Holger Hans Peter Freyther39c430e2015-05-25 12:26:49 +08001561 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001562
1563 /* Cleanup */
1564
Neels Hofmeyr0e5d8072017-01-10 00:49:56 +01001565 gprs_subscr_put(s1);
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001566 sgsn_mm_ctx_cleanup_free(ctx);
1567
1568 assert_no_subscrs();
1569
1570 sgsn_apn_ctx_free(actxs[0]);
1571 sgsn_apn_ctx_free(actxs[1]);
1572 sgsn_apn_ctx_free(actxs[2]);
1573
1574 sgsn_ggsn_ctx_free(ggcs[0]);
1575 sgsn_ggsn_ctx_free(ggcs[1]);
1576 sgsn_ggsn_ctx_free(ggcs[2]);
1577
Harald Weltef4b2c4c2018-09-16 07:53:41 +02001578 osmo_gsup_client_send_cb = __real_osmo_gsup_client_send;
Jacob Erlbeckcf151872015-10-12 19:36:31 +02001579
1580 cleanup_test();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001581}
1582
efistokldef0d942019-04-23 14:37:13 +03001583bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
1584
1585static void test_pdp_status_has_active_nsapis(void)
1586{
1587 const size_t pdp_status_len = 2;
1588 const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
1589 const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
1590 const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
1591
1592 printf("Testing pdp_status_has_active_nsapis\n");
1593
1594 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
1595 OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
1596 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
1597}
1598
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001599static struct log_info_cat gprs_categories[] = {
1600 [DMM] = {
1601 .name = "DMM",
1602 .description = "Layer3 Mobility Management (MM)",
1603 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001604 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001605 },
1606 [DPAG] = {
1607 .name = "DPAG",
1608 .description = "Paging Subsystem",
1609 .color = "\033[1;38m",
1610 .enabled = 1, .loglevel = LOGL_NOTICE,
1611 },
1612 [DMEAS] = {
1613 .name = "DMEAS",
1614 .description = "Radio Measurement Processing",
1615 .enabled = 0, .loglevel = LOGL_NOTICE,
1616 },
1617 [DREF] = {
1618 .name = "DREF",
1619 .description = "Reference Counting",
1620 .enabled = 0, .loglevel = LOGL_NOTICE,
1621 },
1622 [DGPRS] = {
1623 .name = "DGPRS",
1624 .description = "GPRS Packet Service",
1625 .enabled = 1, .loglevel = LOGL_DEBUG,
1626 },
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001627 [DLLC] = {
1628 .name = "DLLC",
1629 .description = "GPRS Logical Link Control Protocol (LLC)",
1630 .enabled = 1, .loglevel = LOGL_DEBUG,
1631 },
1632 [DSNDCP] = {
1633 .name = "DSNDCP",
1634 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1635 .enabled = 1, .loglevel = LOGL_DEBUG,
1636 },
1637};
1638
1639static struct log_info info = {
1640 .cat = gprs_categories,
1641 .num_cat = ARRAY_SIZE(gprs_categories),
1642};
1643
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001644static struct vty_app_info vty_info = {
1645 .name = "testSGSN",
1646};
1647
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001648int main(int argc, char **argv)
1649{
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001650 void *osmo_sgsn_ctx;
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001651 void *msgb_ctx;
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001652
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001653 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
Neels Hofmeyr5bd340e2018-04-16 00:57:10 +02001654 osmo_init_logging2(osmo_sgsn_ctx, &info);
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +01001655 tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001656 msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001657
Pau Espin Pedrola299d652019-08-14 19:11:10 +02001658 vty_init(&vty_info);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +01001659
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001660 test_llme();
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001661 test_subscriber();
Jacob Erlbeck7921ab12014-12-08 15:52:00 +01001662 test_auth_triplets();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +01001663 test_subscriber_gsup();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +02001664 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +01001665 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +02001666 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +01001667 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +01001668 test_gmm_status_no_mmctx();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +01001669 test_gmm_reject();
Jacob Erlbeck98647ca2014-11-11 14:47:38 +01001670 test_gmm_cancel();
Jacob Erlbeckcb1db8b2015-02-03 13:47:53 +01001671 test_apn_matching();
Jacob Erlbeck277b71e2015-02-02 18:03:05 +01001672 test_ggsn_selection();
efistokldef0d942019-04-23 14:37:13 +03001673 test_pdp_status_has_active_nsapis();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001674 printf("Done\n");
Jacob Erlbeck07de92e2015-01-13 11:46:32 +01001675
Jacob Erlbeck4b2d02d2015-01-30 11:57:25 +01001676 talloc_report_full(osmo_sgsn_ctx, stderr);
Neels Hofmeyr39ae17f2016-09-16 01:49:08 +02001677 OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
Pau Espin Pedrole659f752023-01-05 17:20:37 +01001678 OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 1);
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001679 return 0;
1680}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +02001681
1682
1683/* stubs */
1684struct osmo_prim_hdr;
1685int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1686{
1687 abort();
1688}