blob: 533c393c86af02f54401c9f1be98a80599167876 [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/*
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100260 * Test that a single GMM Detach Accept message will not cause the SGSN to send
261 * any message or leave an MM context at the SGSN.
262 */
263static void test_gmm_detach_accept_unexpected(void)
264{
265 struct gprs_llc_lle *lle;
266 uint32_t local_tlli;
267
268 printf("Testing GMM detach accept (unexpected)\n");
269
270 /* DTAP - Detach Accept (MT) */
271 /* normal detach */
272 static const unsigned char detach_acc[] = {
273 0x08, 0x06
274 };
275
276 /* Create an LLME */
277 OSMO_ASSERT(count(gprs_llme_list()) == 0);
278 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
279 lle = gprs_lle_get_or_create(local_tlli, 3);
280
281 /* inject the detach */
282 send_0408_message(lle->llme, local_tlli,
283 detach_acc, ARRAY_SIZE(detach_acc));
284
285 /* verify that no message (and therefore no Status or XID reset) has been
286 * sent by the SGSN */
287 OSMO_ASSERT(sgsn_tx_counter == 0);
288
289 /* verify that things are gone */
290 OSMO_ASSERT(count(gprs_llme_list()) == 0);
291}
292
293/*
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100294 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
295 */
296static void test_gmm_status_no_mmctx(void)
297{
298 struct gprs_llc_lle *lle;
299 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100300
301 printf("Testing GMM Status (no MMCTX)\n");
302
303 /* DTAP - GMM Status, protocol error */
304 static const unsigned char gmm_status[] = {
305 0x08, 0x20, 0x6f
306 };
307
308 /* Create an LLME */
309 OSMO_ASSERT(count(gprs_llme_list()) == 0);
310 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
311 lle = gprs_lle_get_or_create(local_tlli, 3);
312
313 OSMO_ASSERT(count(gprs_llme_list()) == 1);
314
315 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100316 send_0408_message(lle->llme, local_tlli,
317 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100318
319 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100320 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100321
322 /* verify that the LLME is gone */
323 OSMO_ASSERT(count(gprs_llme_list()) == 0);
324}
325
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100326/*
327 * Test the GMM Attach procedure
328 */
329static void test_gmm_attach(void)
330{
331 struct gprs_ra_id raid = { 0, };
332 struct sgsn_mm_ctx *ctx = NULL;
333 struct sgsn_mm_ctx *ictx;
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100334 uint32_t ptmsi1;
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100335 uint32_t foreign_tlli;
336 uint32_t local_tlli = 0;
337 struct gprs_llc_lle *lle;
338
339 /* DTAP - Attach Request */
340 /* The P-TMSI is not known by the SGSN */
341 static const unsigned char attach_req[] = {
342 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
343 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
344 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
345 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
346 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
347 };
348
349 /* DTAP - Identity Response IMEI */
350 static const unsigned char ident_resp_imei[] = {
351 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
352 0x56
353 };
354
355 /* DTAP - Identity Response IMSI */
356 static const unsigned char ident_resp_imsi[] = {
357 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
358 0x54
359 };
360
361 /* DTAP - Attach Complete */
362 static const unsigned char attach_compl[] = {
363 0x08, 0x03
364 };
365
366 /* DTAP - Detach Request (MO) */
367 /* normal detach, power_off = 0 */
368 static const unsigned char detach_req[] = {
369 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
370 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
371 };
372
373 printf("Testing GMM attach\n");
374
375 /* reset the PRNG used by sgsn_alloc_ptmsi */
376 srand(1);
377
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100378 ptmsi1 = sgsn_alloc_ptmsi();
379 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
380
381 /* reset the PRNG, so that the same P-TMSI sequence will be generated
382 * again */
383 srand(1);
384
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100385 sgsn_acl_add("123456789012345", &sgsn->cfg);
386
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100387 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
388
389 /* Create a LLE/LLME */
390 OSMO_ASSERT(count(gprs_llme_list()) == 0);
391 lle = gprs_lle_get_or_create(foreign_tlli, 3);
392 OSMO_ASSERT(count(gprs_llme_list()) == 1);
393
394 /* inject the attach request */
395 send_0408_message(lle->llme, foreign_tlli,
396 attach_req, ARRAY_SIZE(attach_req));
397
398 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
399 OSMO_ASSERT(ctx != NULL);
400 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
401
402 /* we expect an identity request (IMEI) */
403 OSMO_ASSERT(sgsn_tx_counter == 1);
404
405 /* inject the identity response (IMEI) */
406 send_0408_message(ctx->llme, foreign_tlli,
407 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
408
409 /* we expect an identity request (IMSI) */
410 OSMO_ASSERT(sgsn_tx_counter == 1);
411
412 /* inject the identity response (IMSI) */
413 send_0408_message(ctx->llme, foreign_tlli,
414 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
415
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100416 /* check that the MM context has not been removed due to a failed
417 * authorization */
418 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
419
Jacob Erlbeck0074a772014-10-28 16:23:46 +0100420 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100421
422 /* we expect an attach accept/reject */
423 OSMO_ASSERT(sgsn_tx_counter == 1);
424
425 /* this has been randomly assigned by the SGSN */
Jacob Erlbeckaec03a12014-11-24 14:40:28 +0100426 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100427
428 /* inject the attach complete */
429 send_0408_message(ctx->llme, local_tlli,
430 attach_compl, ARRAY_SIZE(attach_compl));
431
432 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
433
434 /* we don't expect a response */
435 OSMO_ASSERT(sgsn_tx_counter == 0);
436
437 /* inject the detach */
438 send_0408_message(ctx->llme, local_tlli,
439 detach_req, ARRAY_SIZE(detach_req));
440
441 /* verify that things are gone */
442 OSMO_ASSERT(count(gprs_llme_list()) == 0);
443 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
444 OSMO_ASSERT(!ictx);
Jacob Erlbeck0c06f982014-10-29 22:12:20 +0100445
446 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100447}
448
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100449/*
450 * Test the GMM Rejects
451 */
452static void test_gmm_reject(void)
453{
454 struct gprs_ra_id raid = { 0, };
455 struct sgsn_mm_ctx *ctx = NULL;
456 uint32_t foreign_tlli;
457 struct gprs_llc_lle *lle;
458 int idx;
459
460 /* DTAP - Attach Request */
461 /* Invalid MI length */
462 static const unsigned char attach_req_inv_mi_len[] = {
463 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
464 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
465 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
466 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
467 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
468 };
469
470 /* DTAP - Attach Request */
471 /* Invalid MI type (IMEI) */
472 static const unsigned char attach_req_inv_mi_type[] = {
473 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
474 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
475 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
476 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
477 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
478 };
479
480 /* DTAP - Routing Area Update Request */
481 static const unsigned char dtap_ra_upd_req[] = {
482 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
483 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
484 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
485 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
486 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
487 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
488 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
489 };
490
491 /* DTAP - Routing Area Update Request */
492 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
493 static const unsigned char dtap_ra_upd_req_inv_type[] = {
494 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
495 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
496 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
497 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
498 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
499 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
500 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
501 };
502
503 /* DTAP - Routing Area Update Request */
504 /* Invalid cap length */
505 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
506 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
507 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
508 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
509 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
510 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
511 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
512 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
513 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
514 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
515 };
516
517 struct test {
518 const char *title;
519 const unsigned char *msg;
520 unsigned msg_len;
521 unsigned num_resp;
522
523 };
524 static struct test tests[] = {
525 {
526 .title = "Attach Request (invalid MI length)",
527 .msg = attach_req_inv_mi_len,
528 .msg_len = sizeof(attach_req_inv_mi_len),
529 .num_resp = 1 /* Reject */
530
531 },
532 {
533 .title = "Attach Request (invalid MI type)",
534 .msg = attach_req_inv_mi_type,
535 .msg_len = sizeof(attach_req_inv_mi_type),
536 .num_resp = 1 /* Reject */
537 },
538 {
539 .title = "Routing Area Update Request (valid)",
540 .msg = dtap_ra_upd_req,
541 .msg_len = sizeof(dtap_ra_upd_req),
542 .num_resp = 2 /* XID Reset + Reject */
543 },
544 {
545 .title = "Routing Area Update Request (invalid type)",
546 .msg = dtap_ra_upd_req_inv_type,
547 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
548 .num_resp = 1 /* Reject */
549 },
550 {
551 .title = "Routing Area Update Request (invalid CAP length)",
552 .msg = dtap_ra_upd_req_inv_cap_len,
553 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
554 .num_resp = 1 /* Reject */
555 },
556 };
557
558 printf("Testing GMM reject\n");
559
560 /* reset the PRNG used by sgsn_alloc_ptmsi */
561 srand(1);
562
563 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
564
565 OSMO_ASSERT(count(gprs_llme_list()) == 0);
566
567 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
568 const struct test *test = &tests[idx];
569 printf(" - %s\n", test->title);
570
571 /* Create a LLE/LLME */
572 lle = gprs_lle_get_or_create(foreign_tlli, 3);
573 OSMO_ASSERT(count(gprs_llme_list()) == 1);
574
575 /* Inject the Request message */
576 send_0408_message(lle->llme, foreign_tlli,
577 test->msg, test->msg_len);
578
579 /* We expect a Reject message */
580 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
581 sgsn_tx_counter, test->num_resp);
582 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
583
584 /* verify that LLME/MM are removed */
585 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
586 OSMO_ASSERT(ctx == NULL);
587 OSMO_ASSERT(count(gprs_llme_list()) == 0);
588 }
589}
590
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100591/*
592 * Test the dynamic allocation of P-TMSIs
593 */
594static void test_gmm_ptmsi_allocation(void)
595{
596 struct gprs_ra_id raid = { 0, };
597 struct sgsn_mm_ctx *ctx = NULL;
598 struct sgsn_mm_ctx *ictx;
599 uint32_t foreign_tlli;
600 uint32_t ptmsi1;
601 uint32_t ptmsi2;
602 uint32_t old_ptmsi;
603 uint32_t local_tlli = 0;
604 struct gprs_llc_lle *lle;
605 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
606
607 /* DTAP - Attach Request (IMSI 12131415161718) */
608 static const unsigned char attach_req[] = {
609 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
610 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
611 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
612 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
613 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
614 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
615 0x00,
616 };
617
618 /* DTAP - Identity Response IMEI */
619 static const unsigned char ident_resp_imei[] = {
620 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
621 0x56
622 };
623
624 /* DTAP - Attach Complete */
625 static const unsigned char attach_compl[] = {
626 0x08, 0x03
627 };
628
629 /* DTAP - Routing Area Update Request */
630 static const unsigned char ra_upd_req[] = {
631 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
632 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
633 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
634 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
635 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
636 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
637 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
638 };
639
640 /* DTAP - Routing Area Update Complete */
641 static const unsigned char ra_upd_complete[] = {
642 0x08, 0x0a
643 };
644
645 /* DTAP - Detach Request (MO) */
646 /* normal detach, power_off = 1 */
647 static const unsigned char detach_req[] = {
648 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
649 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
650 };
651
652 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
653
654 printf("Testing P-TMSI allocation\n");
655
656 printf(" - sgsn_alloc_ptmsi\n");
657
658 /* reset the PRNG used by sgsn_alloc_ptmsi */
659 srand(1);
660
661 ptmsi1 = sgsn_alloc_ptmsi();
662 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
663
664 ptmsi2 = sgsn_alloc_ptmsi();
665 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
666
667 OSMO_ASSERT(ptmsi1 != ptmsi2);
668
669 printf(" - Repeated Attach Request\n");
670
671 /* reset the PRNG, so that the same P-TMSI will be generated
672 * again */
673 srand(1);
674
675 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
676
677 /* Create a LLE/LLME */
678 OSMO_ASSERT(count(gprs_llme_list()) == 0);
679 lle = gprs_lle_get_or_create(foreign_tlli, 3);
680 OSMO_ASSERT(count(gprs_llme_list()) == 1);
681
682 /* inject the attach request */
683 send_0408_message(lle->llme, foreign_tlli,
684 attach_req, ARRAY_SIZE(attach_req));
685
686 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
687 OSMO_ASSERT(ctx != NULL);
688 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
689 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
690
691 old_ptmsi = ctx->p_tmsi_old;
692
693 /* we expect an identity request (IMEI) */
694 OSMO_ASSERT(sgsn_tx_counter == 1);
695
696 /* inject the identity response (IMEI) */
697 send_0408_message(ctx->llme, foreign_tlli,
698 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
699
700 /* check that the MM context has not been removed due to a failed
701 * authorization */
702 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
703
704 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
705 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
706
707 /* we expect an attach accept */
708 OSMO_ASSERT(sgsn_tx_counter == 1);
709
710 /* we ignore this and send the attach again */
711 send_0408_message(lle->llme, foreign_tlli,
712 attach_req, ARRAY_SIZE(attach_req));
713
714 /* the allocated P-TMSI should be the same */
715 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
716 OSMO_ASSERT(ctx != NULL);
717 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
718 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
719 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
720
721 /* inject the attach complete */
722 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
723 send_0408_message(ctx->llme, local_tlli,
724 attach_compl, ARRAY_SIZE(attach_compl));
725
726 /* we don't expect a response */
727 OSMO_ASSERT(sgsn_tx_counter == 0);
728
729 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
730 OSMO_ASSERT(ctx->p_tmsi_old == 0);
731 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
732
733 printf(" - Repeated RA Update Request\n");
734
735 /* inject the RA update request */
736 send_0408_message(ctx->llme, local_tlli,
737 ra_upd_req, ARRAY_SIZE(ra_upd_req));
738
739 /* we expect an RA update accept */
740 OSMO_ASSERT(sgsn_tx_counter == 1);
741
742 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
743 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
744 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
745
746 /* repeat the RA update request */
747 send_0408_message(ctx->llme, local_tlli,
748 ra_upd_req, ARRAY_SIZE(ra_upd_req));
749
750 /* we expect an RA update accept */
751 OSMO_ASSERT(sgsn_tx_counter == 1);
752
753 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
754 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
755 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
756
757 /* inject the RA update complete */
758 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
759 send_0408_message(ctx->llme, local_tlli,
760 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
761
762 /* we don't expect a response */
763 OSMO_ASSERT(sgsn_tx_counter == 0);
764
765 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
766 OSMO_ASSERT(ctx->p_tmsi_old == 0);
767 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
768
769 /* inject the detach */
770 send_0408_message(ctx->llme, local_tlli,
771 detach_req, ARRAY_SIZE(detach_req));
772
773 /* verify that things are gone */
774 OSMO_ASSERT(count(gprs_llme_list()) == 0);
775 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
776 OSMO_ASSERT(!ictx);
777
778 sgsn->cfg.auth_policy = saved_auth_policy;
779}
780
781
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200782static struct log_info_cat gprs_categories[] = {
783 [DMM] = {
784 .name = "DMM",
785 .description = "Layer3 Mobility Management (MM)",
786 .color = "\033[1;33m",
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100787 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200788 },
789 [DPAG] = {
790 .name = "DPAG",
791 .description = "Paging Subsystem",
792 .color = "\033[1;38m",
793 .enabled = 1, .loglevel = LOGL_NOTICE,
794 },
795 [DMEAS] = {
796 .name = "DMEAS",
797 .description = "Radio Measurement Processing",
798 .enabled = 0, .loglevel = LOGL_NOTICE,
799 },
800 [DREF] = {
801 .name = "DREF",
802 .description = "Reference Counting",
803 .enabled = 0, .loglevel = LOGL_NOTICE,
804 },
805 [DGPRS] = {
806 .name = "DGPRS",
807 .description = "GPRS Packet Service",
808 .enabled = 1, .loglevel = LOGL_DEBUG,
809 },
810 [DNS] = {
811 .name = "DNS",
812 .description = "GPRS Network Service (NS)",
813 .enabled = 1, .loglevel = LOGL_INFO,
814 },
815 [DBSSGP] = {
816 .name = "DBSSGP",
817 .description = "GPRS BSS Gateway Protocol (BSSGP)",
818 .enabled = 1, .loglevel = LOGL_DEBUG,
819 },
820 [DLLC] = {
821 .name = "DLLC",
822 .description = "GPRS Logical Link Control Protocol (LLC)",
823 .enabled = 1, .loglevel = LOGL_DEBUG,
824 },
825 [DSNDCP] = {
826 .name = "DSNDCP",
827 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
828 .enabled = 1, .loglevel = LOGL_DEBUG,
829 },
830};
831
832static struct log_info info = {
833 .cat = gprs_categories,
834 .num_cat = ARRAY_SIZE(gprs_categories),
835};
836
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200837int main(int argc, char **argv)
838{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200839 osmo_init_logging(&info);
840 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
841 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
842
Jacob Erlbecka0b6efb2014-11-13 10:48:39 +0100843 sgsn_auth_init();
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100844
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200845 test_llme();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200846 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100847 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200848 test_gmm_detach_no_mmctx();
Jacob Erlbeckde4bbc72014-11-24 15:04:15 +0100849 test_gmm_detach_accept_unexpected();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100850 test_gmm_status_no_mmctx();
Jacob Erlbeck27cb4d52014-10-29 12:11:58 +0100851 test_gmm_attach();
Jacob Erlbeck80d07e32014-11-06 13:43:41 +0100852 test_gmm_reject();
Jacob Erlbeckf6e7d992014-11-06 15:43:10 +0100853 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200854 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200855 return 0;
856}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200857
858
859/* stubs */
860struct osmo_prim_hdr;
861int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
862{
863 abort();
864}