blob: 464f4d742f9eef1db639e99f2fe12059c69f54ee [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
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020022#include <openbsc/gprs_llc.h>
23#include <openbsc/sgsn.h>
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020024#include <openbsc/gprs_gmm.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020025#include <openbsc/debug.h>
26
Jacob Erlbeck189999d2014-10-27 14:34:13 +010027#include <osmocom/gprs/gprs_bssgp.h>
28
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020029#include <osmocom/gsm/gsm_utils.h>
30
31#include <osmocom/core/application.h>
32#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010033#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020034
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020035#include <stdio.h>
36
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020037extern void *tall_msgb_ctx;
38
39void *tall_bsc_ctx;
40static struct sgsn_instance sgsn_inst = {
41 .config_file = "osmo_sgsn.cfg",
42 .cfg = {
43 .gtp_statedir = "./",
Jacob Erlbeck106f5472014-11-04 10:08:37 +010044 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020045 },
46};
47struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010048unsigned sgsn_tx_counter = 0;
49
50/* override */
51int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
52 struct bssgp_dl_ud_par *dup)
53{
54 sgsn_tx_counter += 1;
55 return 0;
56}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020057
58static int count(struct llist_head *head)
59{
60 struct llist_head *cur;
61 int count = 0;
62
63 llist_for_each(cur, head)
64 count += 1;
65
66 return count;
67}
68
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020069static struct msgb *create_msg(const uint8_t *data, size_t len)
70{
71 struct msgb *msg = msgb_alloc(len + 8, "test message");
72 msg->l1h = msgb_put(msg, 8);
73 msg->l2h = msgb_put(msg, len);
74 memcpy(msg->l2h, data, len);
75
76 msgb_bcid(msg) = msg->l1h;
77 msgb_gmmh(msg) = msg->l2h;
78 return msg;
79}
80
Jacob Erlbeckabc16a52014-10-27 13:23:49 +010081/*
82 * Create a context and search for it
83 */
84static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
85{
86 struct sgsn_mm_ctx *ctx, *ictx;
87 struct gprs_llc_lle *lle;
88 int old_count = count(gprs_llme_list());
89
90 lle = gprs_lle_get_or_create(tlli, 3);
91 ctx = sgsn_mm_ctx_alloc(tlli, raid);
92 ctx->mm_state = GMM_REGISTERED_NORMAL;
93 ctx->llme = lle->llme;
94
95 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
96 OSMO_ASSERT(ictx == ctx);
97
98 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
99
100 return ctx;
101}
102
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100103static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
104 const uint8_t *data, size_t data_len)
105{
106 struct msgb *msg;
107
108 sgsn_tx_counter = 0;
109
110 msg = create_msg(data, data_len);
111 msgb_tlli(msg) = tlli;
112 gsm0408_gprs_rcvmsg(msg, llme);
113 msgb_free(msg);
114}
115
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200116static void test_llme(void)
117{
118 struct gprs_llc_lle *lle, *lle_copy;
119 uint32_t local_tlli;
120 uint32_t foreign_tlli;
121
122 printf("Testing LLME allocations\n");
123 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
124 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
125
126 /* initial state */
127 OSMO_ASSERT(count(gprs_llme_list()) == 0);
128
129 /* Create a new entry */
130 lle = gprs_lle_get_or_create(local_tlli, 3);
131 OSMO_ASSERT(lle);
132 OSMO_ASSERT(count(gprs_llme_list()) == 1);
133
134 /* No new entry is created */
135 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
136 OSMO_ASSERT(lle == lle_copy);
137 OSMO_ASSERT(count(gprs_llme_list()) == 1);
138 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
139 OSMO_ASSERT(lle == lle_copy);
140 OSMO_ASSERT(count(gprs_llme_list()) == 1);
141
142 /* unassign which should delete it*/
143 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
144
145 /* Check that everything was cleaned up */
146 OSMO_ASSERT(count(gprs_llme_list()) == 0);
147}
148
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200149/*
150 * Test that a GMM Detach will remove the MMCTX and the
151 * associated LLME.
152 */
153static void test_gmm_detach(void)
154{
155 struct gprs_ra_id raid = { 0, };
156 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200157 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200158
159 printf("Testing GMM detach\n");
160
161 /* DTAP - Detach Request (MO) */
162 /* normal detach, power_off = 0 */
163 static const unsigned char detach_req[] = {
164 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
165 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
166 };
167
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200168 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200169
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100170 /* Create a context */
171 OSMO_ASSERT(count(gprs_llme_list()) == 0);
172 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200173
174 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100175 send_0408_message(ctx->llme, local_tlli,
176 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200177
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100178 /* verify that a single message (hopefully the Detach Accept) has been
179 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100180 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100181
182 /* verify that things are gone */
183 OSMO_ASSERT(count(gprs_llme_list()) == 0);
184 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
185 OSMO_ASSERT(!ictx);
186}
187
188/*
189 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
190 * will not sent a Detach Accept message (power_off = 1)
191 */
192static void test_gmm_detach_power_off(void)
193{
194 struct gprs_ra_id raid = { 0, };
195 struct sgsn_mm_ctx *ctx, *ictx;
196 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100197
198 printf("Testing GMM detach (power off)\n");
199
200 /* DTAP - Detach Request (MO) */
201 /* normal detach, power_off = 1 */
202 static const unsigned char detach_req[] = {
203 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
204 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
205 };
206
207 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
208
209 /* Create a context */
210 OSMO_ASSERT(count(gprs_llme_list()) == 0);
211 ctx = alloc_mm_ctx(local_tlli, &raid);
212
213 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100214 send_0408_message(ctx->llme, local_tlli,
215 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100216
217 /* verify that no message (and therefore no Detach Accept) has been
218 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100219 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100220
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200221 /* verify that things are gone */
222 OSMO_ASSERT(count(gprs_llme_list()) == 0);
223 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200224 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200225}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200226
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200227/*
228 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
229 */
230static void test_gmm_detach_no_mmctx(void)
231{
232 struct gprs_llc_lle *lle;
233 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200234
235 printf("Testing GMM detach (no MMCTX)\n");
236
237 /* DTAP - Detach Request (MO) */
238 /* normal detach, power_off = 0 */
239 static const unsigned char detach_req[] = {
240 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
241 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
242 };
243
244 /* Create an LLME */
245 OSMO_ASSERT(count(gprs_llme_list()) == 0);
246 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
247 lle = gprs_lle_get_or_create(local_tlli, 3);
248
249 OSMO_ASSERT(count(gprs_llme_list()) == 1);
250
251 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100252 send_0408_message(lle->llme, local_tlli,
253 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200254
255 /* verify that the LLME is gone */
256 OSMO_ASSERT(count(gprs_llme_list()) == 0);
257}
258
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100259/*
260 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
261 */
262static void test_gmm_status_no_mmctx(void)
263{
264 struct gprs_llc_lle *lle;
265 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100266
267 printf("Testing GMM Status (no MMCTX)\n");
268
269 /* DTAP - GMM Status, protocol error */
270 static const unsigned char gmm_status[] = {
271 0x08, 0x20, 0x6f
272 };
273
274 /* Create an LLME */
275 OSMO_ASSERT(count(gprs_llme_list()) == 0);
276 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
277 lle = gprs_lle_get_or_create(local_tlli, 3);
278
279 OSMO_ASSERT(count(gprs_llme_list()) == 1);
280
281 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100282 send_0408_message(lle->llme, local_tlli,
283 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100284
285 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100286 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100287
288 /* verify that the LLME is gone */
289 OSMO_ASSERT(count(gprs_llme_list()) == 0);
290}
291
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100292/*
293 * Test the GMM Attach procedure
294 */
295static void test_gmm_attach(void)
296{
297 struct gprs_ra_id raid = { 0, };
298 struct sgsn_mm_ctx *ctx = NULL;
299 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100300 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100301 uint32_t foreign_tlli;
302 uint32_t local_tlli = 0;
303 struct gprs_llc_lle *lle;
304
305 /* DTAP - Attach Request */
306 /* The P-TMSI is not known by the SGSN */
307 static const unsigned char attach_req[] = {
308 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
309 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
310 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
311 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
312 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
313 };
314
315 /* DTAP - Identity Response IMEI */
316 static const unsigned char ident_resp_imei[] = {
317 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
318 0x56
319 };
320
321 /* DTAP - Identity Response IMSI */
322 static const unsigned char ident_resp_imsi[] = {
323 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
324 0x54
325 };
326
327 /* DTAP - Attach Complete */
328 static const unsigned char attach_compl[] = {
329 0x08, 0x03
330 };
331
332 /* DTAP - Detach Request (MO) */
333 /* normal detach, power_off = 0 */
334 static const unsigned char detach_req[] = {
335 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
336 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
337 };
338
339 printf("Testing GMM attach\n");
340
341 /* reset the PRNG used by sgsn_alloc_ptmsi */
342 srand(1);
343
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100344 ptmsi1 = sgsn_alloc_ptmsi();
345 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
346
347 /* reset the PRNG, so that the same P-TMSI sequence will be generated
348 * again */
349 srand(1);
350
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100351 sgsn_acl_add("123456789012345", &sgsn->cfg);
352
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100353 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
354
355 /* Create a LLE/LLME */
356 OSMO_ASSERT(count(gprs_llme_list()) == 0);
357 lle = gprs_lle_get_or_create(foreign_tlli, 3);
358 OSMO_ASSERT(count(gprs_llme_list()) == 1);
359
360 /* inject the attach request */
361 send_0408_message(lle->llme, foreign_tlli,
362 attach_req, ARRAY_SIZE(attach_req));
363
364 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
365 OSMO_ASSERT(ctx != NULL);
366 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
367
368 /* we expect an identity request (IMEI) */
369 OSMO_ASSERT(sgsn_tx_counter == 1);
370
371 /* inject the identity response (IMEI) */
372 send_0408_message(ctx->llme, foreign_tlli,
373 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
374
375 /* we expect an identity request (IMSI) */
376 OSMO_ASSERT(sgsn_tx_counter == 1);
377
378 /* inject the identity response (IMSI) */
379 send_0408_message(ctx->llme, foreign_tlli,
380 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
381
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100382 /* check that the MM context has not been removed due to a failed
383 * authorization */
384 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
385
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100386 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100387
388 /* we expect an attach accept/reject */
389 OSMO_ASSERT(sgsn_tx_counter == 1);
390
391 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100392 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100393
394 /* inject the attach complete */
395 send_0408_message(ctx->llme, local_tlli,
396 attach_compl, ARRAY_SIZE(attach_compl));
397
398 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
399
400 /* we don't expect a response */
401 OSMO_ASSERT(sgsn_tx_counter == 0);
402
403 /* inject the detach */
404 send_0408_message(ctx->llme, local_tlli,
405 detach_req, ARRAY_SIZE(detach_req));
406
407 /* verify that things are gone */
408 OSMO_ASSERT(count(gprs_llme_list()) == 0);
409 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
410 OSMO_ASSERT(!ictx);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100411
412 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100413}
414
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100415/*
416 * Test the GMM Rejects
417 */
418static void test_gmm_reject(void)
419{
420 struct gprs_ra_id raid = { 0, };
421 struct sgsn_mm_ctx *ctx = NULL;
422 uint32_t foreign_tlli;
423 struct gprs_llc_lle *lle;
424 int idx;
425
426 /* DTAP - Attach Request */
427 /* Invalid MI length */
428 static const unsigned char attach_req_inv_mi_len[] = {
429 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
430 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
431 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
432 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
433 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
434 };
435
436 /* DTAP - Attach Request */
437 /* Invalid MI type (IMEI) */
438 static const unsigned char attach_req_inv_mi_type[] = {
439 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
440 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
441 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
442 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
443 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
444 };
445
446 /* DTAP - Routing Area Update Request */
447 static const unsigned char dtap_ra_upd_req[] = {
448 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
449 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
450 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
451 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
452 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
453 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
454 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
455 };
456
457 /* DTAP - Routing Area Update Request */
458 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
459 static const unsigned char dtap_ra_upd_req_inv_type[] = {
460 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
461 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
462 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
463 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
464 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
465 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
466 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
467 };
468
469 /* DTAP - Routing Area Update Request */
470 /* Invalid cap length */
471 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
472 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
473 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
474 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
475 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
476 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
477 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
478 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
479 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
480 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
481 };
482
483 struct test {
484 const char *title;
485 const unsigned char *msg;
486 unsigned msg_len;
487 unsigned num_resp;
488
489 };
490 static struct test tests[] = {
491 {
492 .title = "Attach Request (invalid MI length)",
493 .msg = attach_req_inv_mi_len,
494 .msg_len = sizeof(attach_req_inv_mi_len),
495 .num_resp = 1 /* Reject */
496
497 },
498 {
499 .title = "Attach Request (invalid MI type)",
500 .msg = attach_req_inv_mi_type,
501 .msg_len = sizeof(attach_req_inv_mi_type),
502 .num_resp = 1 /* Reject */
503 },
504 {
505 .title = "Routing Area Update Request (valid)",
506 .msg = dtap_ra_upd_req,
507 .msg_len = sizeof(dtap_ra_upd_req),
508 .num_resp = 2 /* XID Reset + Reject */
509 },
510 {
511 .title = "Routing Area Update Request (invalid type)",
512 .msg = dtap_ra_upd_req_inv_type,
513 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
514 .num_resp = 1 /* Reject */
515 },
516 {
517 .title = "Routing Area Update Request (invalid CAP length)",
518 .msg = dtap_ra_upd_req_inv_cap_len,
519 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
520 .num_resp = 1 /* Reject */
521 },
522 };
523
524 printf("Testing GMM reject\n");
525
526 /* reset the PRNG used by sgsn_alloc_ptmsi */
527 srand(1);
528
529 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
530
531 OSMO_ASSERT(count(gprs_llme_list()) == 0);
532
533 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
534 const struct test *test = &tests[idx];
535 printf(" - %s\n", test->title);
536
537 /* Create a LLE/LLME */
538 lle = gprs_lle_get_or_create(foreign_tlli, 3);
539 OSMO_ASSERT(count(gprs_llme_list()) == 1);
540
541 /* Inject the Request message */
542 send_0408_message(lle->llme, foreign_tlli,
543 test->msg, test->msg_len);
544
545 /* We expect a Reject message */
546 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
547 sgsn_tx_counter, test->num_resp);
548 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
549
550 /* verify that LLME/MM are removed */
551 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
552 OSMO_ASSERT(ctx == NULL);
553 OSMO_ASSERT(count(gprs_llme_list()) == 0);
554 }
555}
556
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100557/*
558 * Test the dynamic allocation of P-TMSIs
559 */
560static void test_gmm_ptmsi_allocation(void)
561{
562 struct gprs_ra_id raid = { 0, };
563 struct sgsn_mm_ctx *ctx = NULL;
564 struct sgsn_mm_ctx *ictx;
565 uint32_t foreign_tlli;
566 uint32_t ptmsi1;
567 uint32_t ptmsi2;
568 uint32_t old_ptmsi;
569 uint32_t local_tlli = 0;
570 struct gprs_llc_lle *lle;
571 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
572
573 /* DTAP - Attach Request (IMSI 12131415161718) */
574 static const unsigned char attach_req[] = {
575 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
576 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
577 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
578 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
579 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
580 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
581 0x00,
582 };
583
584 /* DTAP - Identity Response IMEI */
585 static const unsigned char ident_resp_imei[] = {
586 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
587 0x56
588 };
589
590 /* DTAP - Attach Complete */
591 static const unsigned char attach_compl[] = {
592 0x08, 0x03
593 };
594
595 /* DTAP - Routing Area Update Request */
596 static const unsigned char ra_upd_req[] = {
597 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
598 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
599 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
600 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
601 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
602 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
603 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
604 };
605
606 /* DTAP - Routing Area Update Complete */
607 static const unsigned char ra_upd_complete[] = {
608 0x08, 0x0a
609 };
610
611 /* DTAP - Detach Request (MO) */
612 /* normal detach, power_off = 1 */
613 static const unsigned char detach_req[] = {
614 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
615 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
616 };
617
618 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
619
620 printf("Testing P-TMSI allocation\n");
621
622 printf(" - sgsn_alloc_ptmsi\n");
623
624 /* reset the PRNG used by sgsn_alloc_ptmsi */
625 srand(1);
626
627 ptmsi1 = sgsn_alloc_ptmsi();
628 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
629
630 ptmsi2 = sgsn_alloc_ptmsi();
631 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
632
633 OSMO_ASSERT(ptmsi1 != ptmsi2);
634
635 printf(" - Repeated Attach Request\n");
636
637 /* reset the PRNG, so that the same P-TMSI will be generated
638 * again */
639 srand(1);
640
641 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
642
643 /* Create a LLE/LLME */
644 OSMO_ASSERT(count(gprs_llme_list()) == 0);
645 lle = gprs_lle_get_or_create(foreign_tlli, 3);
646 OSMO_ASSERT(count(gprs_llme_list()) == 1);
647
648 /* inject the attach request */
649 send_0408_message(lle->llme, foreign_tlli,
650 attach_req, ARRAY_SIZE(attach_req));
651
652 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
653 OSMO_ASSERT(ctx != NULL);
654 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
655 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
656
657 old_ptmsi = ctx->p_tmsi_old;
658
659 /* we expect an identity request (IMEI) */
660 OSMO_ASSERT(sgsn_tx_counter == 1);
661
662 /* inject the identity response (IMEI) */
663 send_0408_message(ctx->llme, foreign_tlli,
664 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
665
666 /* check that the MM context has not been removed due to a failed
667 * authorization */
668 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
669
670 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
671 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
672
673 /* we expect an attach accept */
674 OSMO_ASSERT(sgsn_tx_counter == 1);
675
676 /* we ignore this and send the attach again */
677 send_0408_message(lle->llme, foreign_tlli,
678 attach_req, ARRAY_SIZE(attach_req));
679
680 /* the allocated P-TMSI should be the same */
681 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
682 OSMO_ASSERT(ctx != NULL);
683 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
684 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
685 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
686
687 /* inject the attach complete */
688 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
689 send_0408_message(ctx->llme, local_tlli,
690 attach_compl, ARRAY_SIZE(attach_compl));
691
692 /* we don't expect a response */
693 OSMO_ASSERT(sgsn_tx_counter == 0);
694
695 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
696 OSMO_ASSERT(ctx->p_tmsi_old == 0);
697 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
698
699 printf(" - Repeated RA Update Request\n");
700
701 /* inject the RA update request */
702 send_0408_message(ctx->llme, local_tlli,
703 ra_upd_req, ARRAY_SIZE(ra_upd_req));
704
705 /* we expect an RA update accept */
706 OSMO_ASSERT(sgsn_tx_counter == 1);
707
708 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
709 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
710 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
711
712 /* repeat the RA update request */
713 send_0408_message(ctx->llme, local_tlli,
714 ra_upd_req, ARRAY_SIZE(ra_upd_req));
715
716 /* we expect an RA update accept */
717 OSMO_ASSERT(sgsn_tx_counter == 1);
718
719 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
720 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
721 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
722
723 /* inject the RA update complete */
724 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
725 send_0408_message(ctx->llme, local_tlli,
726 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
727
728 /* we don't expect a response */
729 OSMO_ASSERT(sgsn_tx_counter == 0);
730
731 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
732 OSMO_ASSERT(ctx->p_tmsi_old == 0);
733 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
734
735 /* inject the detach */
736 send_0408_message(ctx->llme, local_tlli,
737 detach_req, ARRAY_SIZE(detach_req));
738
739 /* verify that things are gone */
740 OSMO_ASSERT(count(gprs_llme_list()) == 0);
741 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
742 OSMO_ASSERT(!ictx);
743
744 sgsn->cfg.auth_policy = saved_auth_policy;
745}
746
747
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200748static struct log_info_cat gprs_categories[] = {
749 [DMM] = {
750 .name = "DMM",
751 .description = "Layer3 Mobility Management (MM)",
752 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100753 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200754 },
755 [DPAG] = {
756 .name = "DPAG",
757 .description = "Paging Subsystem",
758 .color = "\033[1;38m",
759 .enabled = 1, .loglevel = LOGL_NOTICE,
760 },
761 [DMEAS] = {
762 .name = "DMEAS",
763 .description = "Radio Measurement Processing",
764 .enabled = 0, .loglevel = LOGL_NOTICE,
765 },
766 [DREF] = {
767 .name = "DREF",
768 .description = "Reference Counting",
769 .enabled = 0, .loglevel = LOGL_NOTICE,
770 },
771 [DGPRS] = {
772 .name = "DGPRS",
773 .description = "GPRS Packet Service",
774 .enabled = 1, .loglevel = LOGL_DEBUG,
775 },
776 [DNS] = {
777 .name = "DNS",
778 .description = "GPRS Network Service (NS)",
779 .enabled = 1, .loglevel = LOGL_INFO,
780 },
781 [DBSSGP] = {
782 .name = "DBSSGP",
783 .description = "GPRS BSS Gateway Protocol (BSSGP)",
784 .enabled = 1, .loglevel = LOGL_DEBUG,
785 },
786 [DLLC] = {
787 .name = "DLLC",
788 .description = "GPRS Logical Link Control Protocol (LLC)",
789 .enabled = 1, .loglevel = LOGL_DEBUG,
790 },
791 [DSNDCP] = {
792 .name = "DSNDCP",
793 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
794 .enabled = 1, .loglevel = LOGL_DEBUG,
795 },
796};
797
798static struct log_info info = {
799 .cat = gprs_categories,
800 .num_cat = ARRAY_SIZE(gprs_categories),
801};
802
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200803int main(int argc, char **argv)
804{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200805 osmo_init_logging(&info);
806 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
807 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
808
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +0100809 sgsn_auth_init();
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100810
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200811 test_llme();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200812 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100813 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200814 test_gmm_detach_no_mmctx();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100815 test_gmm_status_no_mmctx();
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100816 test_gmm_attach();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100817 test_gmm_reject();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100818 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200819 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200820 return 0;
821}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200822
823
824/* stubs */
825struct osmo_prim_hdr;
826int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
827{
828 abort();
829}