blob: cc25d47ff97a105c7f1c5269ae5505c8632d596c [file] [log] [blame]
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001/* Test the SGSN */
2/*
3 * (C) 2014 by Holger Hans Peter Freyther
4 * (C) 2014 by sysmocom s.f.m.c. GmbH
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020022#include <osmocom/sgsn/gprs_llc.h>
23#include <osmocom/sgsn/sgsn.h>
24#include <osmocom/sgsn/gprs_gmm.h>
25#include <osmocom/sgsn/debug.h>
26#include <osmocom/sgsn/gprs_subscriber.h>
Harald Welte4e349d62016-04-25 19:07:34 +020027#include <osmocom/gsm/gsup.h>
Harald Welted8f89452018-09-16 07:53:41 +020028#include <osmocom/gsupclient/gsup_client.h>
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020029#include <osmocom/sgsn/gprs_utils.h>
30#include <osmocom/sgsn/gprs_gb_parse.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020031
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010032#include <osmocom/gprs/gprs_bssgp.h>
33
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020034#include <osmocom/gsm/gsm_utils.h>
35
36#include <osmocom/core/application.h>
37#include <osmocom/core/msgb.h>
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010038#include <osmocom/core/rate_ctr.h>
Neels Hofmeyr64a40bf2017-01-13 03:10:54 +010039#include <osmocom/core/utils.h>
Pau Espin Pedrol1b8364d2019-08-14 19:11:10 +020040#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020041
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +020042#include <stdio.h>
43
Pau Espin Pedrold7b95e32018-10-30 17:27:59 +010044void *tall_sgsn_ctx;
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020045static struct sgsn_instance sgsn_inst = {
46 .config_file = "osmo_sgsn.cfg",
47 .cfg = {
48 .gtp_statedir = "./",
Jacob Erlbeckd7b77732014-11-04 10:08:37 +010049 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020050 },
51};
52struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010053unsigned sgsn_tx_counter = 0;
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020054struct msgb *last_msg = NULL;
55struct gprs_gb_parse_context last_dl_parse_ctx;
56
57static void reset_last_msg()
58{
59 if (last_msg)
60 msgb_free(last_msg);
61
62 last_msg = NULL;
63 memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
64}
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010065
Jacob Erlbeck515fc332015-10-12 19:36:31 +020066static void cleanup_test()
67{
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020068 reset_last_msg();
69}
70
71static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
72{
73 uint32_t new_ptmsi = GSM_RESERVED_TMSI;
74
75 if (parse_ctx->new_ptmsi_enc)
76 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
77
78 return new_ptmsi;
Jacob Erlbeck515fc332015-10-12 19:36:31 +020079}
80
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010081/* override */
82int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
83 struct bssgp_dl_ud_par *dup)
84{
Jacob Erlbeck28c28f92015-10-12 19:36:32 +020085 int rc;
86
87 reset_last_msg();
88
89 last_msg = msg;
90 OSMO_ASSERT(msgb_data(last_msg) != NULL);
91
92 rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg),
93 &last_dl_parse_ctx);
94
95 fprintf(stderr, "Got DL LLC message: %s\n",
96 gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN"));
97
98 OSMO_ASSERT(rc > 0);
99
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100100 sgsn_tx_counter += 1;
101 return 0;
102}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200103
Maxca7be8a2017-11-01 13:28:38 +0100104/* override, requires '-Wl,--wrap=osmo_get_rand_id' */
105int __real_osmo_get_rand_id(uint8_t *data, size_t len);
106int mock_osmo_get_rand_id(uint8_t *data, size_t len);
107int (*osmo_get_rand_id_cb)(uint8_t *, size_t) =
108 &mock_osmo_get_rand_id;
Max9943d7a2016-07-05 15:19:12 +0200109
Maxca7be8a2017-11-01 13:28:38 +0100110int __wrap_osmo_get_rand_id(uint8_t *buf, size_t num)
Max9943d7a2016-07-05 15:19:12 +0200111{
Maxca7be8a2017-11-01 13:28:38 +0100112 return (*osmo_get_rand_id_cb)(buf, num);
Max9943d7a2016-07-05 15:19:12 +0200113}
114/* make results of A&C ref predictable */
Maxca7be8a2017-11-01 13:28:38 +0100115int mock_osmo_get_rand_id(uint8_t *buf, size_t num)
Max9943d7a2016-07-05 15:19:12 +0200116{
117 if (num > 1)
Maxca7be8a2017-11-01 13:28:38 +0100118 return __real_osmo_get_rand_id(buf, num);
Max9943d7a2016-07-05 15:19:12 +0200119 buf[0] = 0;
120 return 1;
121}
122
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100123/* override, requires '-Wl,--wrap=sgsn_update_subscriber_data' */
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100124void __real_sgsn_update_subscriber_data(struct sgsn_mm_ctx *);
125void (*update_subscriber_data_cb)(struct sgsn_mm_ctx *) =
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100126 &__real_sgsn_update_subscriber_data;
127
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100128void __wrap_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100129{
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100130 (*update_subscriber_data_cb)(mmctx);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100131}
132
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100133/* override, requires '-Wl,--wrap=gprs_subscr_request_update_location' */
134int __real_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
135int (*subscr_request_update_location_cb)(struct sgsn_mm_ctx *mmctx) =
136 &__real_gprs_subscr_request_update_location;
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100137
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100138int __wrap_gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) {
139 return (*subscr_request_update_location_cb)(mmctx);
140};
141
142/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
Pau Espin Pedrol78a62a52017-08-16 11:30:01 +0200143int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
144int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) =
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100145 &__real_gprs_subscr_request_auth_info;
146
Pau Espin Pedrol78a62a52017-08-16 11:30:01 +0200147int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
148 return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100149};
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100150
Neels Hofmeyr0e5c1e12016-12-08 21:19:57 +0100151/* override, requires '-Wl,--wrap=gsup_client_send' */
Harald Welted8f89452018-09-16 07:53:41 +0200152int __real_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
153int (*osmo_gsup_client_send_cb)(struct osmo_gsup_client *gsupc, struct msgb *msg) =
154 &__real_osmo_gsup_client_send;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100155
Harald Welted8f89452018-09-16 07:53:41 +0200156int __wrap_osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100157{
Harald Welted8f89452018-09-16 07:53:41 +0200158 return (*osmo_gsup_client_send_cb)(gsupc, msg);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +0100159};
160
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200161static int count(struct llist_head *head)
162{
163 struct llist_head *cur;
164 int count = 0;
165
166 llist_for_each(cur, head)
167 count += 1;
168
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100169 return count;
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200170}
171
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200172static struct msgb *create_msg(const uint8_t *data, size_t len)
173{
174 struct msgb *msg = msgb_alloc(len + 8, "test message");
175 msg->l1h = msgb_put(msg, 8);
176 msg->l2h = msgb_put(msg, len);
177 memcpy(msg->l2h, data, len);
178
179 msgb_bcid(msg) = msg->l1h;
180 msgb_gmmh(msg) = msg->l2h;
181 return msg;
182}
183
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100184/*
185 * Create a context and search for it
186 */
187static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
188{
189 struct sgsn_mm_ctx *ctx, *ictx;
190 struct gprs_llc_lle *lle;
191 int old_count = count(gprs_llme_list());
192
193 lle = gprs_lle_get_or_create(tlli, 3);
Alexander Couzens1c7869e2017-02-04 06:01:00 +0100194 ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
Alexander Couzens5e33f442017-01-31 15:34:26 +0100195 ctx->gmm_state = GMM_REGISTERED_NORMAL;
Harald Weltec28dc2f2015-12-25 19:12:21 +0100196 ctx->gb.llme = lle->llme;
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100197
198 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
199 OSMO_ASSERT(ictx == ctx);
200
201 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
202
203 return ctx;
204}
205
Jacob Erlbeck75488292014-10-29 10:31:18 +0100206static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100207 const struct gprs_ra_id *bssgp_raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100208 const uint8_t *data, size_t data_len)
209{
210 struct msgb *msg;
211
Jacob Erlbeck28c28f92015-10-12 19:36:32 +0200212 reset_last_msg();
Jacob Erlbeck75488292014-10-29 10:31:18 +0100213 sgsn_tx_counter = 0;
214
215 msg = create_msg(data, data_len);
216 msgb_tlli(msg) = tlli;
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100217 bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
Max4bc28212016-07-06 11:59:18 +0200218 gsm0408_gprs_rcvmsg_gb(msg, llme, false);
Jacob Erlbeck75488292014-10-29 10:31:18 +0100219 msgb_free(msg);
220}
221
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200222static void test_llme(void)
223{
224 struct gprs_llc_lle *lle, *lle_copy;
225 uint32_t local_tlli;
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200226
227 printf("Testing LLME allocations\n");
228 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200229
230 /* initial state */
231 OSMO_ASSERT(count(gprs_llme_list()) == 0);
232
233 /* Create a new entry */
234 lle = gprs_lle_get_or_create(local_tlli, 3);
235 OSMO_ASSERT(lle);
236 OSMO_ASSERT(count(gprs_llme_list()) == 1);
237
238 /* No new entry is created */
239 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
240 OSMO_ASSERT(lle == lle_copy);
241 OSMO_ASSERT(count(gprs_llme_list()) == 1);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200242
243 /* unassign which should delete it*/
Maxa86f5c02016-06-28 17:39:20 +0200244 gprs_llgmm_unassign(lle->llme);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200245
246 /* Check that everything was cleaned up */
247 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200248
249 cleanup_test();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200250}
251
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100252struct gprs_subscr *last_updated_subscr = NULL;
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100253void my_dummy_sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100254{
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100255 OSMO_ASSERT(mmctx);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100256 fprintf(stderr, "Called %s, mmctx = %p, subscr = %p\n",
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100257 __func__, mmctx, mmctx->subscr);
258 last_updated_subscr = mmctx->subscr;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100259}
260
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100261static void assert_subscr(const struct gprs_subscr *subscr, const char *imsi)
Jacob Erlbecka695d242015-01-09 11:59:50 +0100262{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100263 struct gprs_subscr *sfound;
Jacob Erlbeckf3df29d2015-01-19 08:57:07 +0100264 OSMO_ASSERT(subscr);
265 OSMO_ASSERT(strcmp(subscr->imsi, imsi) == 0);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100266
267 sfound = gprs_subscr_get_by_imsi(imsi);
268 OSMO_ASSERT(sfound == subscr);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100269
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100270 gprs_subscr_put(sfound);
Jacob Erlbecka695d242015-01-09 11:59:50 +0100271}
272
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100273static void show_subscrs(FILE *out)
274{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100275 struct gprs_subscr *subscr;
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100276
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100277 llist_for_each_entry(subscr, gprs_subscribers, entry) {
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100278 fprintf(out, " Subscriber: %s, "
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100279 "use count: %d\n",
280 subscr->imsi, subscr->use_count);
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100281 }
282}
283
284static void assert_no_subscrs()
285{
286 show_subscrs(stdout);
287 fflush(stdout);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100288 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbeck8768f2b2015-01-13 11:46:32 +0100289}
290
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100291#define VERBOSE_ASSERT(val, expect_op, fmt) \
292 do { \
293 printf(#val " == " fmt "\n", (val)); \
294 OSMO_ASSERT((val) expect_op); \
295 } while (0);
296
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100297static void test_subscriber(void)
298{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100299 struct gprs_subscr *s1, *s2, *s3;
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100300 const char *imsi1 = "1234567890";
301 const char *imsi2 = "9876543210";
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100302 const char *imsi3 = "5656565656";
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100303
304 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
305
306 printf("Testing core subscriber data API\n");
307
308 /* Check for emptiness */
309 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
310 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100311 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100312 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100313
314 /* Allocate entry 1 */
315 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100316 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
317 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka695d242015-01-09 11:59:50 +0100318 assert_subscr(s1, imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100319 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100320 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100321
322 /* Allocate entry 2 */
323 s2 = gprs_subscr_get_or_create(imsi2);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100324 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
325 s2->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbecka695d242015-01-09 11:59:50 +0100326
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100327 /* Allocate entry 3 */
328 s3 = gprs_subscr_get_or_create(imsi3);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100329 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 3, "%d");
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100330
Jacob Erlbecka695d242015-01-09 11:59:50 +0100331 /* Check entries */
332 assert_subscr(s1, imsi1);
333 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100334 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100335
336 /* Update entry 1 */
337 last_updated_subscr = NULL;
338 gprs_subscr_update(s1);
Jacob Erlbeck428f1ec2015-01-26 13:52:42 +0100339 OSMO_ASSERT(last_updated_subscr == NULL);
340 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100341 OSMO_ASSERT((s1->flags & GPRS_SUBSCRIBER_FIRST_CONTACT) == 0);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100342
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100343 /* There is no subscriber cache. Verify it */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100344 gprs_subscr_cleanup(s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100345 gprs_subscr_put(s1);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100346 s1 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100347 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 2, "%d");
348 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100349
Jacob Erlbecka695d242015-01-09 11:59:50 +0100350 assert_subscr(s2, imsi2);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100351 assert_subscr(s3, imsi3);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100352
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100353 /* Free entry 2 (GPRS_SUBSCRIBER_FIRST_CONTACT is set) */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100354 gprs_subscr_cleanup(s2);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100355 gprs_subscr_put(s2);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100356 s2 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100357 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 1, "%d");
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100358 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
359 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi2) == NULL);
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100360 assert_subscr(s3, imsi3);
361
362 /* Try to delete entry 3 */
Jacob Erlbecke71ab2f2015-01-26 11:07:24 +0100363 gprs_subscr_cleanup(s3);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100364 gprs_subscr_put(s3);
Holger Hans Peter Freytherd95cb732015-01-20 21:14:03 +0100365 s3 = NULL;
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100366 VERBOSE_ASSERT(llist_count(gprs_subscribers), == 0, "%d");
Jacob Erlbeck9bf4be92015-01-06 16:32:41 +0100367 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi3) == NULL);
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100368
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100369 OSMO_ASSERT(llist_empty(gprs_subscribers));
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100370
371 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200372
373 cleanup_test();
Jacob Erlbecke8b69682014-11-12 10:12:11 +0100374}
375
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100376static void test_auth_triplets(void)
377{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100378 struct gprs_subscr *s1, *s1found;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100379 const char *imsi1 = "1234567890";
380 struct gsm_auth_tuple *at;
381 struct sgsn_mm_ctx *ctx;
382 struct gprs_ra_id raid = { 0, };
383 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100384
385 printf("Testing authentication triplet handling\n");
386
387 /* Check for emptiness */
388 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
389
390 /* Allocate entry 1 */
391 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100392 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100393 s1found = gprs_subscr_get_by_imsi(imsi1);
394 OSMO_ASSERT(s1found == s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100395 gprs_subscr_put(s1found);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100396
397 /* Create a context */
398 OSMO_ASSERT(count(gprs_llme_list()) == 0);
399 ctx = alloc_mm_ctx(local_tlli, &raid);
400
401 /* Attach s1 to ctx */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100402 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100403 ctx->subscr->sgsn_data->mm = ctx;
404
405 /* Try to get auth tuple */
406 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
407 OSMO_ASSERT(at == NULL);
408
409 /* Add triplets */
410 s1->sgsn_data->auth_triplets[0].key_seq = 0;
411 s1->sgsn_data->auth_triplets[1].key_seq = 1;
412 s1->sgsn_data->auth_triplets[2].key_seq = 2;
413
414 /* Try to get auth tuple */
415 at = sgsn_auth_get_tuple(ctx, GSM_KEY_SEQ_INVAL);
416 OSMO_ASSERT(at != NULL);
417 OSMO_ASSERT(at->key_seq == 0);
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 == 1);
422 OSMO_ASSERT(at->use_count == 1);
423 at = sgsn_auth_get_tuple(ctx, at->key_seq);
424 OSMO_ASSERT(at != NULL);
425 OSMO_ASSERT(at->key_seq == 2);
426 OSMO_ASSERT(at->use_count == 1);
427 at = sgsn_auth_get_tuple(ctx, at->key_seq);
428 OSMO_ASSERT(at == NULL);
429
430 /* Free MM context and subscriber */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100431 gprs_subscr_put(s1);
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100432 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100433 s1found = gprs_subscr_get_by_imsi(imsi1);
434 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200435
436 cleanup_test();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +0100437}
438
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100439#define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09
440
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100441static int rx_gsup_message(const uint8_t *data, size_t data_len)
442{
443 struct msgb *msg;
444 int rc;
445
446 msg = msgb_alloc(1024, __func__);
447 msg->l2h = msgb_put(msg, data_len);
448 OSMO_ASSERT(msg->l2h != NULL);
449 memcpy(msg->l2h, data, data_len);
450 rc = gprs_subscr_rx_gsup_message(msg);
451 msgb_free(msg);
452
453 return rc;
454}
455
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100456static void test_subscriber_gsup(void)
457{
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100458 struct gprs_subscr *s1, *s1found;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100459 const char *imsi1 = "1234567890";
460 struct sgsn_mm_ctx *ctx;
461 struct gprs_ra_id raid = { 0, };
462 uint32_t local_tlli = 0xffeeddcc;
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100463 struct sgsn_subscriber_pdp_data *pdpd;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100464 int rc;
465
466 static const uint8_t send_auth_info_res[] = {
467 0x0a,
468 TEST_GSUP_IMSI1_IE,
469 0x03, 0x22, /* Auth tuple */
470 0x20, 0x10,
471 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
472 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
473 0x21, 0x04,
474 0x21, 0x22, 0x23, 0x24,
475 0x22, 0x08,
476 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
477 0x03, 0x22, /* Auth tuple */
478 0x20, 0x10,
479 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
480 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
481 0x21, 0x04,
482 0xa1, 0xa2, 0xa3, 0xa4,
483 0x22, 0x08,
484 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
485 };
486
487 static const uint8_t send_auth_info_err[] = {
488 0x09,
489 TEST_GSUP_IMSI1_IE,
490 0x02, 0x01, 0x07 /* GPRS not allowed */
491 };
492
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400493#define MSISDN 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
494
495 static const uint8_t s1_msisdn[] = { MSISDN };
496
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100497 static const uint8_t update_location_res[] = {
498 0x06,
499 TEST_GSUP_IMSI1_IE,
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400500 0x08, 0x09, MSISDN,
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100501 0x04, 0x00, /* PDP info complete */
502 0x05, 0x12,
503 0x10, 0x01, 0x01,
504 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
505 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
506 0x05, 0x11,
507 0x10, 0x01, 0x02,
508 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
509 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
510 };
511
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400512#undef MSISDN
513
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100514 static const uint8_t update_location_err[] = {
515 0x05,
516 TEST_GSUP_IMSI1_IE,
517 0x02, 0x01, 0x07 /* GPRS not allowed */
518 };
519
520 static const uint8_t location_cancellation_req[] = {
521 0x1c,
522 TEST_GSUP_IMSI1_IE,
523 0x06, 0x01, 0x00,
524 };
525
Jacob Erlbecke7fea452015-04-07 17:49:48 +0200526 static const uint8_t location_cancellation_req_withdraw[] = {
527 0x1c,
528 TEST_GSUP_IMSI1_IE,
529 0x06, 0x01, 0x01,
530 };
531
Jacob Erlbeck00b8b912015-01-08 15:29:01 +0100532 static const uint8_t location_cancellation_req_other[] = {
533 0x1c,
534 0x01, 0x05, 0x11, 0x11, 0x11, 0x11, 0x01,
535 0x06, 0x01, 0x00,
536 };
537
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100538 static const uint8_t purge_ms_err[] = {
539 0x0d,
540 TEST_GSUP_IMSI1_IE,
541 0x02, 0x01, 0x02, /* IMSI unknown in HLR */
542 };
543
Jacob Erlbeck9ca3ace2015-01-29 14:17:51 +0100544 static const uint8_t purge_ms_err_no_cause[] = {
545 0x0d,
546 TEST_GSUP_IMSI1_IE,
547 };
548
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100549 static const uint8_t purge_ms_res[] = {
550 0x0e,
551 TEST_GSUP_IMSI1_IE,
552 0x07, 0x00,
553 };
554
555
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100556 static const uint8_t insert_data_req[] = {
557 0x10,
558 TEST_GSUP_IMSI1_IE,
559 0x05, 0x11,
560 0x10, 0x01, 0x03,
561 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
562 0x12, 0x08, 0x03, 'b', 'a', 'r', 0x03, 'a', 'p', 'n',
563 };
564
565 static const uint8_t delete_data_req[] = {
566 0x14,
567 TEST_GSUP_IMSI1_IE,
568 0x10, 0x01, 0x03,
569 };
570
Neels Hofmeyr2b91ce22016-06-20 18:26:15 +0200571 printf("Testing subscriber GSUP handling\n");
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100572
573 update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
574
575 /* Check for emptiness */
576 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
577
578 /* Allocate entry 1 */
579 s1 = gprs_subscr_get_or_create(imsi1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100580 s1->flags |= GPRS_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100581 s1found = gprs_subscr_get_by_imsi(imsi1);
582 OSMO_ASSERT(s1found == s1);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100583 gprs_subscr_put(s1found);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100584
585 /* Create a context */
586 OSMO_ASSERT(count(gprs_llme_list()) == 0);
587 ctx = alloc_mm_ctx(local_tlli, &raid);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100588
589 /* Attach s1 to ctx */
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100590 ctx->subscr = gprs_subscr_get(s1);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100591 ctx->subscr->sgsn_data->mm = ctx;
592
593 /* Inject SendAuthInfoReq GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100594 rc = rx_gsup_message(send_auth_info_res, sizeof(send_auth_info_res));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100595 OSMO_ASSERT(rc >= 0);
596 OSMO_ASSERT(last_updated_subscr == s1);
597
598 /* Check triplets */
599 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == 0);
600 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == 1);
601 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
602
603 /* Inject SendAuthInfoErr GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100604 rc = rx_gsup_message(send_auth_info_err, sizeof(send_auth_info_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100605 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100606 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100607 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100608
609 /* Check triplets */
610 OSMO_ASSERT(s1->sgsn_data->auth_triplets[0].key_seq == GSM_KEY_SEQ_INVAL);
611 OSMO_ASSERT(s1->sgsn_data->auth_triplets[1].key_seq == GSM_KEY_SEQ_INVAL);
612 OSMO_ASSERT(s1->sgsn_data->auth_triplets[2].key_seq == GSM_KEY_SEQ_INVAL);
613
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100614 /* Inject UpdateLocRes GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100615 rc = rx_gsup_message(update_location_res, sizeof(update_location_res));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100616 OSMO_ASSERT(rc >= 0);
617 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100618 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100619 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Holger Hans Peter Freyther786cfee2015-04-23 09:53:53 -0400620 OSMO_ASSERT(s1->sgsn_data->msisdn_len == sizeof(s1_msisdn));
621 OSMO_ASSERT(memcmp(s1->sgsn_data->msisdn, s1_msisdn, sizeof(s1_msisdn)) == 0);
Jacob Erlbeck94a346a2014-12-17 14:03:35 +0100622 OSMO_ASSERT(!llist_empty(&s1->sgsn_data->pdp_list));
623 pdpd = llist_entry(s1->sgsn_data->pdp_list.next,
624 struct sgsn_subscriber_pdp_data, list);
625 OSMO_ASSERT(strcmp(pdpd->apn_str, "test.apn") == 0);
626 pdpd = llist_entry(pdpd->list.next,
627 struct sgsn_subscriber_pdp_data, list);
628 OSMO_ASSERT(strcmp(pdpd->apn_str, "foo.apn") == 0);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100629
630 /* Check authorization */
631 OSMO_ASSERT(s1->authorized == 1);
632
633 /* Inject UpdateLocErr GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100634 rc = rx_gsup_message(update_location_err, sizeof(update_location_err));
Jacob Erlbeck092bbc82015-01-05 18:57:32 +0100635 OSMO_ASSERT(rc == -GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100636 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100637 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_GPRS_NOTALLOWED);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100638
639 /* Check authorization */
640 OSMO_ASSERT(s1->authorized == 0);
641
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100642 /* Inject InsertSubscrData GSUP message */
643 last_updated_subscr = NULL;
644 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Harald Weltee7e3f272016-11-26 14:58:36 +0100645 OSMO_ASSERT(rc == -ENOTSUP); /* not connected */
Harald Welted3356e72016-05-06 13:46:21 +0200646 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100647
648 /* Inject DeleteSubscrData GSUP message */
649 last_updated_subscr = NULL;
650 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
Maxe405f152017-02-15 11:43:59 +0100651 if (rc != -GMM_CAUSE_SEM_INCORR_MSG)
652 printf("Unexpected response to DSD: %d\n", rc);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100653 OSMO_ASSERT(last_updated_subscr == NULL);
654
Jacob Erlbeck00b8b912015-01-08 15:29:01 +0100655 /* Inject wrong LocCancelReq GSUP message */
656 last_updated_subscr = NULL;
657 rc = rx_gsup_message(location_cancellation_req_other,
658 sizeof(location_cancellation_req_other));
659 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
660 OSMO_ASSERT(last_updated_subscr == NULL);
661
662 /* Check cancellation result */
663 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_CANCELLED));
664 OSMO_ASSERT(s1->sgsn_data->mm != NULL);
665
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100666 /* Inject LocCancelReq GSUP message */
Jacob Erlbeckb5c51432014-12-19 18:19:50 +0100667 rc = rx_gsup_message(location_cancellation_req,
668 sizeof(location_cancellation_req));
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100669 OSMO_ASSERT(rc >= 0);
670 OSMO_ASSERT(last_updated_subscr == s1);
Jacob Erlbeck736da132015-01-29 14:55:34 +0100671 OSMO_ASSERT(s1->sgsn_data->error_cause == SGSN_ERROR_CAUSE_NONE);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100672
673 /* Check cancellation result */
674 OSMO_ASSERT(s1->flags & GPRS_SUBSCRIBER_CANCELLED);
675 OSMO_ASSERT(s1->sgsn_data->mm == NULL);
676
Jacob Erlbecke7fea452015-04-07 17:49:48 +0200677 /* Inject LocCancelReq(withdraw) GSUP message */
678 rc = rx_gsup_message(location_cancellation_req_withdraw,
679 sizeof(location_cancellation_req_withdraw));
680 OSMO_ASSERT(rc >= 0);
681 OSMO_ASSERT(s1->sgsn_data->error_cause == GMM_CAUSE_IMPL_DETACHED);
682
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100683 /* Inject PurgeMsRes GSUP message */
684 rc = rx_gsup_message(purge_ms_res,
685 sizeof(purge_ms_res));
686 OSMO_ASSERT(rc >= 0);
687 OSMO_ASSERT(!(s1->flags & GPRS_SUBSCRIBER_ENABLE_PURGE));
688
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100689 /* Free MM context and subscriber */
Jacob Erlbeck265e7352015-01-30 11:57:25 +0100690 OSMO_ASSERT(ctx->subscr == NULL);
691 sgsn_mm_ctx_cleanup_free(ctx);
Neels Hofmeyre2c94d62017-01-10 00:49:56 +0100692 gprs_subscr_put(s1);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100693 s1found = gprs_subscr_get_by_imsi(imsi1);
694 OSMO_ASSERT(s1found == NULL);
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100695
Jacob Erlbeck86bc8702015-01-29 14:12:29 +0100696 /* Inject PurgeMsRes GSUP message */
697 rc = rx_gsup_message(purge_ms_res,
698 sizeof(purge_ms_res));
699 OSMO_ASSERT(rc >= 0);
700
701 /* Inject PurgeMsErr(IMSI unknown in HLR) GSUP message */
702 rc = rx_gsup_message(purge_ms_err,
703 sizeof(purge_ms_err));
704 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
705
Jacob Erlbeck9ca3ace2015-01-29 14:17:51 +0100706 /* Inject PurgeMsErr() GSUP message */
707 rc = rx_gsup_message(purge_ms_err_no_cause,
708 sizeof(purge_ms_err_no_cause));
709 OSMO_ASSERT(rc == -GMM_CAUSE_NET_FAIL);
710
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100711 /* Inject InsertSubscrData GSUP message (unknown IMSI) */
712 last_updated_subscr = NULL;
713 rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
Jacob Erlbeck629dacc2015-01-15 17:50:16 +0100714 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
Jacob Erlbeck4f414862015-01-15 17:08:30 +0100715 OSMO_ASSERT(last_updated_subscr == NULL);
716
717 /* Inject DeleteSubscrData GSUP message (unknown IMSI) */
718 rc = rx_gsup_message(delete_data_req, sizeof(delete_data_req));
719 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
720 OSMO_ASSERT(last_updated_subscr == NULL);
721
722 /* Inject LocCancelReq GSUP message (unknown IMSI) */
723 rc = rx_gsup_message(location_cancellation_req,
724 sizeof(location_cancellation_req));
725 OSMO_ASSERT(rc == -GMM_CAUSE_IMSI_UNKNOWN);
726 OSMO_ASSERT(last_updated_subscr == NULL);
727
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100728 update_subscriber_data_cb = __real_sgsn_update_subscriber_data;
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200729
730 cleanup_test();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +0100731}
732
Harald Welted8f89452018-09-16 07:53:41 +0200733int my_gsup_client_send_dummy(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeckfdf8ce52015-01-08 16:23:25 +0100734{
735 msgb_free(msg);
736 return 0;
737};
738
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200739/*
740 * Test that a GMM Detach will remove the MMCTX and the
741 * associated LLME.
742 */
743static void test_gmm_detach(void)
744{
745 struct gprs_ra_id raid = { 0, };
746 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200747 uint32_t local_tlli;
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200748
749 printf("Testing GMM detach\n");
750
751 /* DTAP - Detach Request (MO) */
752 /* normal detach, power_off = 0 */
753 static const unsigned char detach_req[] = {
754 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
755 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
756 };
757
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200758 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200759
Jacob Erlbeckf43a2992014-10-27 13:23:49 +0100760 /* Create a context */
761 OSMO_ASSERT(count(gprs_llme_list()) == 0);
762 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200763
764 /* inject the detach */
Harald Weltec28dc2f2015-12-25 19:12:21 +0100765 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100766 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200767
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100768 /* verify that a single message (hopefully the Detach Accept) has been
769 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100770 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100771
772 /* verify that things are gone */
773 OSMO_ASSERT(count(gprs_llme_list()) == 0);
774 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
775 OSMO_ASSERT(!ictx);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200776
777 cleanup_test();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100778}
779
780/*
781 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
782 * will not sent a Detach Accept message (power_off = 1)
783 */
784static void test_gmm_detach_power_off(void)
785{
786 struct gprs_ra_id raid = { 0, };
787 struct sgsn_mm_ctx *ctx, *ictx;
788 uint32_t local_tlli;
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100789
790 printf("Testing GMM detach (power off)\n");
791
792 /* DTAP - Detach Request (MO) */
793 /* normal detach, power_off = 1 */
794 static const unsigned char detach_req[] = {
795 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
796 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
797 };
798
799 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
800
801 /* Create a context */
802 OSMO_ASSERT(count(gprs_llme_list()) == 0);
803 ctx = alloc_mm_ctx(local_tlli, &raid);
804
805 /* inject the detach */
Harald Weltec28dc2f2015-12-25 19:12:21 +0100806 send_0408_message(ctx->gb.llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100807 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100808
809 /* verify that no message (and therefore no Detach Accept) has been
810 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100811 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100812
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200813 /* verify that things are gone */
814 OSMO_ASSERT(count(gprs_llme_list()) == 0);
815 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck12396bd2014-09-30 13:51:45 +0200816 OSMO_ASSERT(!ictx);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200817
818 cleanup_test();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200819}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200820
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200821/*
822 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
823 */
824static void test_gmm_detach_no_mmctx(void)
825{
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +0100826 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200827 struct gprs_llc_lle *lle;
828 uint32_t local_tlli;
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200829
830 printf("Testing GMM detach (no MMCTX)\n");
831
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 Erlbeck2d9dee92016-01-04 18:43:33 +0100847 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100848 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200849
850 /* verify that the LLME is gone */
851 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200852
853 cleanup_test();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200854}
855
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100856/*
Jacob Erlbeck021a0d12014-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 Erlbeck2d9dee92016-01-04 18:43:33 +0100862 struct gprs_ra_id raid = { 0, };
Jacob Erlbeck021a0d12014-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 Erlbeck2d9dee92016-01-04 18:43:33 +0100880 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck021a0d12014-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 Erlbeck515fc332015-10-12 19:36:31 +0200889
890 cleanup_test();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +0100891}
892
893/*
Jacob Erlbeckb35ee6b2014-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 Erlbeck2d9dee92016-01-04 18:43:33 +0100898 struct gprs_ra_id raid = { 0, };
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100899 struct gprs_llc_lle *lle;
900 uint32_t local_tlli;
Jacob Erlbeckb35ee6b2014-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 Erlbeck2d9dee92016-01-04 18:43:33 +0100917 send_0408_message(lle->llme, local_tlli, &raid,
Jacob Erlbeck75488292014-10-29 10:31:18 +0100918 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100919
920 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100921 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100922
923 /* verify that the LLME is gone */
924 OSMO_ASSERT(count(gprs_llme_list()) == 0);
Jacob Erlbeck515fc332015-10-12 19:36:31 +0200925
926 cleanup_test();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100927}
928
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100929int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
930{
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100931 int rc;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100932 rc = __real_gprs_subscr_request_update_location(mmctx);
Jacob Erlbeckd04f7cc2014-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 Pedrol964dcb22018-01-07 18:07:17 +0100938}
Jacob Erlbeckd04f7cc2014-11-12 10:18:09 +0100939
Pau Espin Pedrold17d6212018-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 Erlbeck828059f2014-11-28 14:55:25 +0100943 gprs_subscr_update(mmctx->subscr);
944 return 0;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100945}
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100946
Pau Espin Pedrold17d6212018-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 Erlbeck828059f2014-11-28 14:55:25 +0100949{
950 /* Fake an authentication */
951 OSMO_ASSERT(mmctx->subscr);
Neels Hofmeyr4a8d5012018-04-22 19:29:41 +0200952 mmctx->sec_ctx = OSMO_AUTH_TYPE_GSM;
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100953 gprs_subscr_update_auth_info(mmctx->subscr);
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100954
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100955 return 0;
Pau Espin Pedrol964dcb22018-01-07 18:07:17 +0100956}
Jacob Erlbeckd8126992014-12-08 15:26:47 +0100957
Pau Espin Pedrol78a62a52017-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 Erlbeck828059f2014-11-28 14:55:25 +0100959{
960 struct gsm_auth_tuple at = {
Harald Welte34ef4c52016-04-20 13:13:19 +0200961 .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
Neels Hofmeyr4eec3df2017-02-24 06:24:45 +0100962 .vec.auth_types = OSMO_AUTH_TYPE_GSM,
Jacob Erlbeck828059f2014-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 Pedrol964dcb22018-01-07 18:07:17 +0100973}
Jacob Erlbeck828059f2014-11-28 14:55:25 +0100974
Jacob Erlbeckdebbdd72014-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 Erlbeck803ebfa2014-12-19 18:30:41 +0100978static int auth_info_skip = 0;
979static int upd_loc_skip = 0;
980
Pau Espin Pedrold17d6212018-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 Erlbeckdebbdd72014-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 Erlbeck0d2cf602015-01-09 15:07:16 +0100997 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +0100998
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +0100999 if (auth_info_skip > 0) {
1000 auth_info_skip -= 1;
1001 return -EAGAIN;
1002 }
1003
Jacob Erlbeckdebbdd72014-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 Freythera9f671c2015-05-05 22:52:40 +02001019 0x08, 0x07, /* MSISDN 49166213323 encoded */
1020 0x91, 0x94, 0x61, 0x26, 0x31, 0x23, 0xF3,
Holger Hans Peter Freytherfe4a9f62015-05-17 20:58:40 +02001021 0x09, 0x07, /* MSISDN 38166213323 encoded */
1022 0x91, 0x83, 0x61, 0x26, 0x31, 0x23, 0xF3,
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001023 };
1024
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001025 OSMO_ASSERT(!mmctx || mmctx->subscr);
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001026
Jacob Erlbeck803ebfa2014-12-19 18:30:41 +01001027 if (upd_loc_skip > 0) {
1028 upd_loc_skip -= 1;
1029 return -EAGAIN;
1030 }
1031
Jacob Erlbeckdebbdd72014-12-19 18:26:09 +01001032 /* Fake an UpdateLocRes */
1033 return rx_gsup_message(update_location_res, sizeof(update_location_res));
1034};
1035
Harald Welted8f89452018-09-16 07:53:41 +02001036int my_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg)
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001037{
Harald Welte4e349d62016-04-25 19:07:34 +02001038 struct osmo_gsup_message to_peer = {0};
1039 struct osmo_gsup_message from_peer = {0};
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001040 struct msgb *reply_msg;
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001041 int rc;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001042
1043 /* Simulate the GSUP peer */
Harald Welte4e349d62016-04-25 19:07:34 +02001044 rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001045 OSMO_ASSERT(rc >= 0);
1046 OSMO_ASSERT(to_peer.imsi[0] != 0);
Neels Hofmeyr64a40bf2017-01-13 03:10:54 +01001047 osmo_strlcpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
Jacob Erlbeck0d2cf602015-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 Welte4e349d62016-04-25 19:07:34 +02001053 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001054 /* Send UPDATE_LOCATION_RESULT */
1055 return my_subscr_request_update_gsup_auth(NULL);
1056
Harald Welte4e349d62016-04-25 19:07:34 +02001057 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001058 /* Send SEND_AUTH_INFO_RESULT */
Pau Espin Pedrold17d6212018-01-07 18:05:22 +01001059 return my_subscr_request_auth_info_gsup_auth(NULL, NULL, NULL);
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001060
Harald Welte4e349d62016-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 Erlbeckb3982c12015-01-06 16:32:41 +01001063 break;
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001064
1065 default:
1066 if ((to_peer.message_type & 0b00000011) == 0) {
1067 /* Unhandled request */
Jacob Erlbeckb3982c12015-01-06 16:32:41 +01001068 /* Send error(NOT_IMPL) */
Jacob Erlbeck0d2cf602015-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 Welted8f89452018-09-16 07:53:41 +02001078 reply_msg = osmo_gsup_client_msgb_alloc();
Jacob Erlbeck0d2cf602015-01-09 15:07:16 +01001079 reply_msg->l2h = reply_msg->data;
Harald Welte4e349d62016-04-25 19:07:34 +02001080 osmo_gsup_encode(reply_msg, &from_peer);
Jacob Erlbeck0d2cf602015-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 Erlbeck6f4bbd42014-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");
1197
1198 /* reset the PRNG used by sgsn_alloc_ptmsi */
1199 srand(1);
1200
1201 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1202
1203 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1204
1205 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
1206 const struct test *test = &tests[idx];
1207 printf(" - %s\n", test->title);
1208
1209 /* Create a LLE/LLME */
1210 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1211 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1212
1213 /* Inject the Request message */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +01001214 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001215 test->msg, test->msg_len);
1216
1217 /* We expect a Reject message */
1218 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
1219 sgsn_tx_counter, test->num_resp);
1220 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
1221
1222 /* verify that LLME/MM are removed */
1223 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1224 OSMO_ASSERT(ctx == NULL);
1225 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1226 }
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001227
1228 cleanup_test();
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001229}
1230
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001231/*
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001232 * Test cancellation of attached MM contexts
1233 */
1234static void test_gmm_cancel(void)
1235{
1236 struct gprs_ra_id raid = { 0, };
1237 struct sgsn_mm_ctx *ctx = NULL;
1238 struct sgsn_mm_ctx *ictx;
1239 uint32_t ptmsi1;
1240 uint32_t foreign_tlli;
1241 uint32_t local_tlli = 0;
1242 struct gprs_llc_lle *lle;
1243 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
1244
1245 /* DTAP - Attach Request */
1246 /* The P-TMSI is not known by the SGSN */
1247 static const unsigned char attach_req[] = {
1248 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
1249 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
1250 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
1251 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
1252 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
1253 };
1254
1255 /* DTAP - Identity Response IMEI */
1256 static const unsigned char ident_resp_imei[] = {
1257 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
1258 0x56
1259 };
1260
1261 /* DTAP - Identity Response IMSI */
1262 static const unsigned char ident_resp_imsi[] = {
1263 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
1264 0x54
1265 };
1266
1267 /* DTAP - Attach Complete */
1268 static const unsigned char attach_compl[] = {
1269 0x08, 0x03
1270 };
1271
1272 printf("Testing cancellation\n");
1273
1274 sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
1275
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001276 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
1277
1278 /* Create a LLE/LLME */
1279 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1280 lle = gprs_lle_get_or_create(foreign_tlli, 3);
1281 OSMO_ASSERT(count(gprs_llme_list()) == 1);
1282
1283 /* inject the attach request */
Jacob Erlbeck2d9dee92016-01-04 18:43:33 +01001284 send_0408_message(lle->llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001285 attach_req, ARRAY_SIZE(attach_req));
1286
1287 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
1288 OSMO_ASSERT(ctx != NULL);
Alexander Couzens5e33f442017-01-31 15:34:26 +01001289 OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001290
1291 /* we expect an identity request (IMEI) */
1292 OSMO_ASSERT(sgsn_tx_counter == 1);
1293
1294 /* inject the identity response (IMEI) */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001295 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001296 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
1297
1298 /* we expect an identity request (IMSI) */
1299 OSMO_ASSERT(sgsn_tx_counter == 1);
1300
1301 /* inject the identity response (IMSI) */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001302 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001303 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
1304
1305 /* check that the MM context has not been removed due to a failed
1306 * authorization */
1307 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
1308
Alexander Couzens5e33f442017-01-31 15:34:26 +01001309 OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001310
1311 /* we expect an attach accept/reject */
1312 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck28c28f92015-10-12 19:36:32 +02001313 ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx);
1314 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001315
1316 /* this has been randomly assigned by the SGSN */
1317 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
1318
1319 /* inject the attach complete */
Harald Weltec28dc2f2015-12-25 19:12:21 +01001320 send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001321 attach_compl, ARRAY_SIZE(attach_compl));
1322
Alexander Couzens5e33f442017-01-31 15:34:26 +01001323 OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001324
1325 /* we don't expect a response */
1326 OSMO_ASSERT(sgsn_tx_counter == 0);
1327
1328 /* cancel */
Jacob Erlbeck41010082015-01-05 17:51:17 +01001329 gsm0408_gprs_access_cancelled(ctx, 0);
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001330
1331 /* verify that things are gone */
1332 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1333 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
1334 OSMO_ASSERT(!ictx);
1335
1336 sgsn->cfg.auth_policy = saved_auth_policy;
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001337
1338 cleanup_test();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001339}
1340
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001341static void test_apn_matching(void)
1342{
1343 struct apn_ctx *actx, *actxs[9];
1344
1345 printf("Testing APN matching\n");
1346
1347 actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
1348 actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
1349 actxs[2] = sgsn_apn_ctx_find_alloc("abc.def.test", "");
1350 actxs[3] = NULL;
1351
1352 actxs[4] = sgsn_apn_ctx_find_alloc("abc.def.test", "456");
1353 actxs[5] = sgsn_apn_ctx_find_alloc("abc.def.test", "456123");
1354 actxs[6] = sgsn_apn_ctx_find_alloc("*.def.test", "456");
1355 actxs[7] = sgsn_apn_ctx_find_alloc("*.def.test", "456123");
1356
1357 actxs[8] = sgsn_apn_ctx_find_alloc("ghi.def.test", "456");
1358
1359 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1360 OSMO_ASSERT(actx == actxs[2]);
1361 actx = sgsn_apn_ctx_match("aBc.dEf.test", "12345678");
1362 OSMO_ASSERT(actx == actxs[2]);
1363 actx = sgsn_apn_ctx_match("xyz.def.test", "12345678");
1364 OSMO_ASSERT(actx == actxs[1]);
1365 actx = sgsn_apn_ctx_match("xyz.dEf.test", "12345678");
1366 OSMO_ASSERT(actx == actxs[1]);
1367 actx = sgsn_apn_ctx_match("xyz.uvw.test", "12345678");
1368 OSMO_ASSERT(actx == actxs[0]);
1369 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1370 OSMO_ASSERT(actx == NULL);
1371
1372 actxs[3] = sgsn_apn_ctx_find_alloc("*", "");
1373 actx = sgsn_apn_ctx_match("xyz.uvw.foo", "12345678");
1374 OSMO_ASSERT(actx == actxs[3]);
1375
1376 actx = sgsn_apn_ctx_match("abc.def.test", "45699900");
1377 OSMO_ASSERT(actx == actxs[4]);
1378
1379 actx = sgsn_apn_ctx_match("xyz.def.test", "45699900");
1380 OSMO_ASSERT(actx == actxs[6]);
1381
1382 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1383 OSMO_ASSERT(actx == actxs[5]);
1384
1385 actx = sgsn_apn_ctx_match("xyz.def.test", "45612300");
1386 OSMO_ASSERT(actx == actxs[7]);
1387
1388 actx = sgsn_apn_ctx_match("ghi.def.test", "45699900");
1389 OSMO_ASSERT(actx == actxs[8]);
1390
1391 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1392 OSMO_ASSERT(actx == actxs[7]);
1393
1394 /* Free APN contexts and check how the matching changes */
1395
1396 sgsn_apn_ctx_free(actxs[7]);
1397 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1398 OSMO_ASSERT(actx == actxs[8]);
1399
1400 sgsn_apn_ctx_free(actxs[8]);
1401 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1402 OSMO_ASSERT(actx == actxs[6]);
1403
1404 sgsn_apn_ctx_free(actxs[6]);
1405 actx = sgsn_apn_ctx_match("ghi.def.test", "45612300");
1406 OSMO_ASSERT(actx == actxs[1]);
1407
1408 sgsn_apn_ctx_free(actxs[5]);
1409 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1410 OSMO_ASSERT(actx == actxs[4]);
1411
1412 sgsn_apn_ctx_free(actxs[4]);
1413 actx = sgsn_apn_ctx_match("abc.def.test", "45612300");
1414 OSMO_ASSERT(actx == actxs[2]);
1415
1416 sgsn_apn_ctx_free(actxs[2]);
1417 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1418 OSMO_ASSERT(actx == actxs[1]);
1419
1420 sgsn_apn_ctx_free(actxs[1]);
1421 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1422 OSMO_ASSERT(actx == actxs[0]);
1423
1424 sgsn_apn_ctx_free(actxs[0]);
1425 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1426 OSMO_ASSERT(actx == actxs[3]);
1427
1428 sgsn_apn_ctx_free(actxs[3]);
1429 actx = sgsn_apn_ctx_match("abc.def.test", "12345678");
1430 OSMO_ASSERT(actx == NULL);
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001431
1432 cleanup_test();
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001433}
1434
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001435struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
1436 struct sgsn_subscriber_data *sdata);
1437
1438static void test_ggsn_selection(void)
1439{
1440 struct apn_ctx *actxs[4];
1441 struct sgsn_ggsn_ctx *ggc, *ggcs[3];
Neels Hofmeyre2c94d62017-01-10 00:49:56 +01001442 struct gprs_subscr *s1;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001443 const char *imsi1 = "1234567890";
1444 struct sgsn_mm_ctx *ctx;
1445 struct gprs_ra_id raid = { 0, };
1446 uint32_t local_tlli = 0xffeeddcc;
1447 enum gsm48_gsm_cause gsm_cause;
1448 struct tlv_parsed tp;
1449 uint8_t apn_enc[GSM_APN_LENGTH + 10];
1450 struct sgsn_subscriber_pdp_data *pdp_data;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001451 char apn_str[GSM_APN_LENGTH];
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001452
1453 printf("Testing GGSN selection\n");
1454
Harald Welted8f89452018-09-16 07:53:41 +02001455 osmo_gsup_client_send_cb = my_gsup_client_send_dummy;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001456
1457 /* Check for emptiness */
1458 OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
1459
1460 /* Create a context */
1461 OSMO_ASSERT(count(gprs_llme_list()) == 0);
1462 ctx = alloc_mm_ctx(local_tlli, &raid);
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001463 osmo_strlcpy(ctx->imsi, imsi1, sizeof(ctx->imsi));
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001464
1465 /* Allocate and attach a subscriber */
1466 s1 = gprs_subscr_get_or_create_by_mmctx(ctx);
1467 assert_subscr(s1, imsi1);
1468
1469 tp.lv[GSM48_IE_GSM_APN].len = 0;
1470 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1471
1472 /* TODO: Add PDP info entries to s1 */
1473
1474 ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
1475 ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
1476 ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
1477
1478 actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
1479 actxs[0]->ggsn = ggcs[0];
1480 actxs[1] = sgsn_apn_ctx_find_alloc("*.apn", "123456");
1481 actxs[1]->ggsn = ggcs[1];
1482 actxs[2] = sgsn_apn_ctx_find_alloc("*", "456789");
1483 actxs[2]->ggsn = ggcs[2];
1484
Holger Hans Peter Freytherab9422e2015-05-24 20:51:17 +08001485 pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
1486 pdp_data->context_id = 1;
1487 pdp_data->pdp_type = 0x0121;
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001488 osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
Holger Hans Peter Freytherab9422e2015-05-24 20:51:17 +08001489
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001490 /* Resolve GGSNs */
1491
1492 tp.lv[GSM48_IE_GSM_APN].len =
1493 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1494
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001495 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001496 OSMO_ASSERT(ggc != NULL);
1497 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001498 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001499
1500 tp.lv[GSM48_IE_GSM_APN].len =
1501 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1502
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001503 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001504 OSMO_ASSERT(ggc != NULL);
1505 OSMO_ASSERT(ggc->id == 1);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001506 OSMO_ASSERT(strcmp(apn_str, "Other.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001507
1508 tp.lv[GSM48_IE_GSM_APN].len = 0;
1509 tp.lv[GSM48_IE_GSM_APN].val = NULL;
1510
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001511 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001512 OSMO_ASSERT(ggc != NULL);
1513 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001514 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001515
1516 actxs[3] = sgsn_apn_ctx_find_alloc("*", "123456");
1517 actxs[3]->ggsn = ggcs[2];
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001518 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001519 OSMO_ASSERT(ggc != NULL);
1520 OSMO_ASSERT(ggc->id == 2);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001521 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001522
1523 sgsn_apn_ctx_free(actxs[3]);
1524 tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
1525
1526 tp.lv[GSM48_IE_GSM_APN].len =
1527 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
1528
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001529 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001530 OSMO_ASSERT(ggc == NULL);
1531 OSMO_ASSERT(gsm_cause == GSM_CAUSE_MISSING_APN);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001532 OSMO_ASSERT(strcmp(apn_str, "Foo.Bar") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001533
1534 tp.lv[GSM48_IE_GSM_APN].len = sizeof(apn_enc);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001535 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001536 OSMO_ASSERT(ggc == NULL);
1537 OSMO_ASSERT(gsm_cause == GSM_CAUSE_INV_MAND_INFO);
1538
1539 /* Add PDP data entry to subscriber */
1540
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001541 osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001542
1543 tp.lv[GSM48_IE_GSM_APN].len =
1544 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
1545
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001546 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001547 OSMO_ASSERT(ggc != NULL);
1548 OSMO_ASSERT(ggc->id == 0);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001549 OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001550
1551 tp.lv[GSM48_IE_GSM_APN].len =
1552 gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
1553
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001554 ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001555 OSMO_ASSERT(ggc == NULL);
1556 OSMO_ASSERT(gsm_cause == GSM_CAUSE_REQ_SERV_OPT_NOTSUB);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001557 OSMO_ASSERT(strcmp(apn_str, "") == 0);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001558
1559 /* Cleanup */
1560
Neels Hofmeyre2c94d62017-01-10 00:49:56 +01001561 gprs_subscr_put(s1);
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001562 sgsn_mm_ctx_cleanup_free(ctx);
1563
1564 assert_no_subscrs();
1565
1566 sgsn_apn_ctx_free(actxs[0]);
1567 sgsn_apn_ctx_free(actxs[1]);
1568 sgsn_apn_ctx_free(actxs[2]);
1569
1570 sgsn_ggsn_ctx_free(ggcs[0]);
1571 sgsn_ggsn_ctx_free(ggcs[1]);
1572 sgsn_ggsn_ctx_free(ggcs[2]);
1573
Harald Welted8f89452018-09-16 07:53:41 +02001574 osmo_gsup_client_send_cb = __real_osmo_gsup_client_send;
Jacob Erlbeck515fc332015-10-12 19:36:31 +02001575
1576 cleanup_test();
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001577}
1578
efistoklb842c032019-04-23 14:37:13 +03001579bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
1580
1581static void test_pdp_status_has_active_nsapis(void)
1582{
1583 const size_t pdp_status_len = 2;
1584 const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
1585 const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
1586 const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
1587
1588 printf("Testing pdp_status_has_active_nsapis\n");
1589
1590 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
1591 OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
1592 OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
1593}
1594
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001595static struct log_info_cat gprs_categories[] = {
1596 [DMM] = {
1597 .name = "DMM",
1598 .description = "Layer3 Mobility Management (MM)",
1599 .color = "\033[1;33m",
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001600 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001601 },
1602 [DPAG] = {
1603 .name = "DPAG",
1604 .description = "Paging Subsystem",
1605 .color = "\033[1;38m",
1606 .enabled = 1, .loglevel = LOGL_NOTICE,
1607 },
1608 [DMEAS] = {
1609 .name = "DMEAS",
1610 .description = "Radio Measurement Processing",
1611 .enabled = 0, .loglevel = LOGL_NOTICE,
1612 },
1613 [DREF] = {
1614 .name = "DREF",
1615 .description = "Reference Counting",
1616 .enabled = 0, .loglevel = LOGL_NOTICE,
1617 },
1618 [DGPRS] = {
1619 .name = "DGPRS",
1620 .description = "GPRS Packet Service",
1621 .enabled = 1, .loglevel = LOGL_DEBUG,
1622 },
1623 [DNS] = {
1624 .name = "DNS",
1625 .description = "GPRS Network Service (NS)",
1626 .enabled = 1, .loglevel = LOGL_INFO,
1627 },
1628 [DBSSGP] = {
1629 .name = "DBSSGP",
1630 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1631 .enabled = 1, .loglevel = LOGL_DEBUG,
1632 },
1633 [DLLC] = {
1634 .name = "DLLC",
1635 .description = "GPRS Logical Link Control Protocol (LLC)",
1636 .enabled = 1, .loglevel = LOGL_DEBUG,
1637 },
1638 [DSNDCP] = {
1639 .name = "DSNDCP",
1640 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
1641 .enabled = 1, .loglevel = LOGL_DEBUG,
1642 },
1643};
1644
1645static struct log_info info = {
1646 .cat = gprs_categories,
1647 .num_cat = ARRAY_SIZE(gprs_categories),
1648};
1649
Pau Espin Pedrol1b8364d2019-08-14 19:11:10 +02001650static struct vty_app_info vty_info = {
1651 .name = "testSGSN",
1652};
1653
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001654int main(int argc, char **argv)
1655{
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001656 void *osmo_sgsn_ctx;
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001657 void *msgb_ctx;
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001658
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001659 osmo_sgsn_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
Neels Hofmeyr8de6b862018-04-16 00:57:10 +02001660 osmo_init_logging2(osmo_sgsn_ctx, &info);
Pau Espin Pedrold7b95e32018-10-30 17:27:59 +01001661 tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001662 msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001663
Alexander Couzens32fdba02016-07-05 09:52:52 +02001664 sgsn_rate_ctr_init();
Maxbc1d4f02018-12-10 18:01:47 +01001665 sgsn_auth_init(sgsn);
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001666 gprs_subscr_init(sgsn);
Pau Espin Pedrol1b8364d2019-08-14 19:11:10 +02001667 vty_init(&vty_info);
1668 sgsn_vty_init(&sgsn->cfg);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +01001669
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001670 test_llme();
Jacob Erlbecke8b69682014-11-12 10:12:11 +01001671 test_subscriber();
Jacob Erlbeckb1332b62014-12-08 15:52:00 +01001672 test_auth_triplets();
Jacob Erlbeck5641cfc2014-12-12 15:01:37 +01001673 test_subscriber_gsup();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +02001674 test_gmm_detach();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +01001675 test_gmm_detach_power_off();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001676 test_gmm_detach_no_mmctx();
Jacob Erlbeck021a0d12014-11-24 15:04:15 +01001677 test_gmm_detach_accept_unexpected();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001678 test_gmm_status_no_mmctx();
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001679 test_gmm_reject();
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001680 test_gmm_cancel();
Jacob Erlbeck9b3ca642015-02-03 13:47:53 +01001681 test_apn_matching();
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001682 test_ggsn_selection();
efistoklb842c032019-04-23 14:37:13 +03001683 test_pdp_status_has_active_nsapis();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001684 printf("Done\n");
Jacob Erlbeck80dbcf12015-01-13 11:46:32 +01001685
Jacob Erlbeck265e7352015-01-30 11:57:25 +01001686 talloc_report_full(osmo_sgsn_ctx, stderr);
Neels Hofmeyra73e5f12016-09-16 01:49:08 +02001687 OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
Pau Espin Pedrold7b95e32018-10-30 17:27:59 +01001688 OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 2);
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +02001689 return 0;
1690}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +02001691
1692
1693/* stubs */
1694struct osmo_prim_hdr;
1695int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
1696{
1697 abort();
1698}