blob: d6091fdab0e3e91c29dcd366fd9cd7d7387c1e21 [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
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020022#include <openbsc/gprs_llc.h>
23#include <openbsc/sgsn.h>
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +020024#include <openbsc/gprs_gmm.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020025#include <openbsc/debug.h>
26
Jacob Erlbeck0b2da872014-10-27 14:34:13 +010027#include <osmocom/gprs/gprs_bssgp.h>
28
Holger Hans Peter Freyther49dbcd92014-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 Erlbeck0b2da872014-10-27 14:34:13 +010033#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020034
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +020035#include <stdio.h>
36
Holger Hans Peter Freyther49dbcd92014-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 Erlbeckd7b77732014-11-04 10:08:37 +010044 .auth_policy = SGSN_AUTH_POLICY_CLOSED,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +020045 },
46};
47struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck0b2da872014-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 Freyther49dbcd92014-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 Freyther94246842014-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 Erlbeckf43a2992014-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 Erlbeck75488292014-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 Freyther49dbcd92014-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 Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200157 uint32_t local_tlli;
Holger Hans Peter Freyther94246842014-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 Freyther94246842014-10-02 22:24:47 +0200168 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200169
Jacob Erlbeckf43a2992014-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 Freyther94246842014-10-02 22:24:47 +0200173
174 /* inject the detach */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100175 send_0408_message(ctx->llme, local_tlli,
176 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200177
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100178 /* verify that a single message (hopefully the Detach Accept) has been
179 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100180 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck0b2da872014-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 Erlbeck0b2da872014-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 Erlbeck75488292014-10-29 10:31:18 +0100214 send_0408_message(ctx->llme, local_tlli,
215 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100216
217 /* verify that no message (and therefore no Detach Accept) has been
218 * sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100219 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100220
Holger Hans Peter Freyther94246842014-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 Erlbeck12396bd2014-09-30 13:51:45 +0200224 OSMO_ASSERT(!ictx);
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200225}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200226
Jacob Erlbeck42d284f2014-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 Erlbeck42d284f2014-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 Erlbeck75488292014-10-29 10:31:18 +0100252 send_0408_message(lle->llme, local_tlli,
253 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200254
255 /* verify that the LLME is gone */
256 OSMO_ASSERT(count(gprs_llme_list()) == 0);
257}
258
Jacob Erlbeckb35ee6b2014-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 Erlbeckb35ee6b2014-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 Erlbeck75488292014-10-29 10:31:18 +0100282 send_0408_message(lle->llme, local_tlli,
283 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100284
285 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck75488292014-10-29 10:31:18 +0100286 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100287
288 /* verify that the LLME is gone */
289 OSMO_ASSERT(count(gprs_llme_list()) == 0);
290}
291
Jacob Erlbeck7c24b3e2014-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;
300 uint32_t foreign_tlli;
301 uint32_t local_tlli = 0;
302 struct gprs_llc_lle *lle;
303
304 /* DTAP - Attach Request */
305 /* The P-TMSI is not known by the SGSN */
306 static const unsigned char attach_req[] = {
307 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf4,
308 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
309 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
310 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
311 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
312 };
313
314 /* DTAP - Identity Response IMEI */
315 static const unsigned char ident_resp_imei[] = {
316 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
317 0x56
318 };
319
320 /* DTAP - Identity Response IMSI */
321 static const unsigned char ident_resp_imsi[] = {
322 0x08, 0x16, 0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32,
323 0x54
324 };
325
326 /* DTAP - Attach Complete */
327 static const unsigned char attach_compl[] = {
328 0x08, 0x03
329 };
330
331 /* DTAP - Detach Request (MO) */
332 /* normal detach, power_off = 0 */
333 static const unsigned char detach_req[] = {
334 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xeb, 0x8b,
335 0x45, 0x67, 0x19, 0x03, 0xb9, 0x97, 0xcb
336 };
337
338 printf("Testing GMM attach\n");
339
340 /* reset the PRNG used by sgsn_alloc_ptmsi */
341 srand(1);
342
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100343 sgsn_acl_add("123456789012345", &sgsn->cfg);
344
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100345 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
346
347 /* Create a LLE/LLME */
348 OSMO_ASSERT(count(gprs_llme_list()) == 0);
349 lle = gprs_lle_get_or_create(foreign_tlli, 3);
350 OSMO_ASSERT(count(gprs_llme_list()) == 1);
351
352 /* inject the attach request */
353 send_0408_message(lle->llme, foreign_tlli,
354 attach_req, ARRAY_SIZE(attach_req));
355
356 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
357 OSMO_ASSERT(ctx != NULL);
358 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
359
360 /* we expect an identity request (IMEI) */
361 OSMO_ASSERT(sgsn_tx_counter == 1);
362
363 /* inject the identity response (IMEI) */
364 send_0408_message(ctx->llme, foreign_tlli,
365 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
366
367 /* we expect an identity request (IMSI) */
368 OSMO_ASSERT(sgsn_tx_counter == 1);
369
370 /* inject the identity response (IMSI) */
371 send_0408_message(ctx->llme, foreign_tlli,
372 ident_resp_imsi, ARRAY_SIZE(ident_resp_imsi));
373
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100374 /* check that the MM context has not been removed due to a failed
375 * authorization */
376 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
377
Jacob Erlbeck67318ef2014-10-28 16:23:46 +0100378 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100379
380 /* we expect an attach accept/reject */
381 OSMO_ASSERT(sgsn_tx_counter == 1);
382
383 /* this has been randomly assigned by the SGSN */
384 local_tlli = gprs_tmsi2tlli(0xeb8b4567, TLLI_LOCAL);
385
386 /* inject the attach complete */
387 send_0408_message(ctx->llme, local_tlli,
388 attach_compl, ARRAY_SIZE(attach_compl));
389
390 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
391
392 /* we don't expect a response */
393 OSMO_ASSERT(sgsn_tx_counter == 0);
394
395 /* inject the detach */
396 send_0408_message(ctx->llme, local_tlli,
397 detach_req, ARRAY_SIZE(detach_req));
398
399 /* verify that things are gone */
400 OSMO_ASSERT(count(gprs_llme_list()) == 0);
401 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
402 OSMO_ASSERT(!ictx);
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100403
404 sgsn_acl_del("123456789012345", &sgsn->cfg);
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100405}
406
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +0100407/*
408 * Test the GMM Rejects
409 */
410static void test_gmm_reject(void)
411{
412 struct gprs_ra_id raid = { 0, };
413 struct sgsn_mm_ctx *ctx = NULL;
414 uint32_t foreign_tlli;
415 struct gprs_llc_lle *lle;
416 int idx;
417
418 /* DTAP - Attach Request */
419 /* Invalid MI length */
420 static const unsigned char attach_req_inv_mi_len[] = {
421 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x09, 0xf4,
422 0xfb, 0xc5, 0x46, 0x79, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22,
423 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25,
424 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00,
425 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
426 };
427
428 /* DTAP - Attach Request */
429 /* Invalid MI type (IMEI) */
430 static const unsigned char attach_req_inv_mi_type[] = {
431 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02, 0x05, 0xf2,
432 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
433 0x19, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
434 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
435 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00
436 };
437
438 /* DTAP - Routing Area Update Request */
439 static const unsigned char dtap_ra_upd_req[] = {
440 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
441 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
442 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
443 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
444 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
445 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
446 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
447 };
448
449 /* DTAP - Routing Area Update Request */
450 /* Invalid type: GPRS_UPD_T_RA_LA_IMSI_ATT */
451 static const unsigned char dtap_ra_upd_req_inv_type[] = {
452 0x08, 0x08, 0x12, 0x11, 0x22, 0x33, 0x40, 0x50,
453 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
454 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
455 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
456 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
457 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
458 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
459 };
460
461 /* DTAP - Routing Area Update Request */
462 /* Invalid cap length */
463 static const unsigned char dtap_ra_upd_req_inv_cap_len[] = {
464 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
465 0x60, 0x3d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
466 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
467 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
468 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
469 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
470 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
471 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
472 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
473 };
474
475 struct test {
476 const char *title;
477 const unsigned char *msg;
478 unsigned msg_len;
479 unsigned num_resp;
480
481 };
482 static struct test tests[] = {
483 {
484 .title = "Attach Request (invalid MI length)",
485 .msg = attach_req_inv_mi_len,
486 .msg_len = sizeof(attach_req_inv_mi_len),
487 .num_resp = 1 /* Reject */
488
489 },
490 {
491 .title = "Attach Request (invalid MI type)",
492 .msg = attach_req_inv_mi_type,
493 .msg_len = sizeof(attach_req_inv_mi_type),
494 .num_resp = 1 /* Reject */
495 },
496 {
497 .title = "Routing Area Update Request (valid)",
498 .msg = dtap_ra_upd_req,
499 .msg_len = sizeof(dtap_ra_upd_req),
500 .num_resp = 2 /* XID Reset + Reject */
501 },
502 {
503 .title = "Routing Area Update Request (invalid type)",
504 .msg = dtap_ra_upd_req_inv_type,
505 .msg_len = sizeof(dtap_ra_upd_req_inv_type),
506 .num_resp = 1 /* Reject */
507 },
508 {
509 .title = "Routing Area Update Request (invalid CAP length)",
510 .msg = dtap_ra_upd_req_inv_cap_len,
511 .msg_len = sizeof(dtap_ra_upd_req_inv_cap_len),
512 .num_resp = 1 /* Reject */
513 },
514 };
515
516 printf("Testing GMM reject\n");
517
518 /* reset the PRNG used by sgsn_alloc_ptmsi */
519 srand(1);
520
521 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
522
523 OSMO_ASSERT(count(gprs_llme_list()) == 0);
524
525 for (idx = 0; idx < ARRAY_SIZE(tests); idx++) {
526 const struct test *test = &tests[idx];
527 printf(" - %s\n", test->title);
528
529 /* Create a LLE/LLME */
530 lle = gprs_lle_get_or_create(foreign_tlli, 3);
531 OSMO_ASSERT(count(gprs_llme_list()) == 1);
532
533 /* Inject the Request message */
534 send_0408_message(lle->llme, foreign_tlli,
535 test->msg, test->msg_len);
536
537 /* We expect a Reject message */
538 fprintf(stderr, "sgsn_tx_counter = %d (expected %d)\n",
539 sgsn_tx_counter, test->num_resp);
540 OSMO_ASSERT(sgsn_tx_counter == test->num_resp);
541
542 /* verify that LLME/MM are removed */
543 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
544 OSMO_ASSERT(ctx == NULL);
545 OSMO_ASSERT(count(gprs_llme_list()) == 0);
546 }
547}
548
Jacob Erlbecke06476a2014-11-06 15:43:10 +0100549/*
550 * Test the dynamic allocation of P-TMSIs
551 */
552static void test_gmm_ptmsi_allocation(void)
553{
554 struct gprs_ra_id raid = { 0, };
555 struct sgsn_mm_ctx *ctx = NULL;
556 struct sgsn_mm_ctx *ictx;
557 uint32_t foreign_tlli;
558 uint32_t ptmsi1;
559 uint32_t ptmsi2;
560 uint32_t old_ptmsi;
561 uint32_t local_tlli = 0;
562 struct gprs_llc_lle *lle;
563 const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
564
565 /* DTAP - Attach Request (IMSI 12131415161718) */
566 static const unsigned char attach_req[] = {
567 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
568 0x08, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
569 0x18, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19,
570 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00,
571 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60,
572 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80,
573 0x00,
574 };
575
576 /* DTAP - Identity Response IMEI */
577 static const unsigned char ident_resp_imei[] = {
578 0x08, 0x16, 0x08, 0x9a, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78,
579 0x56
580 };
581
582 /* DTAP - Attach Complete */
583 static const unsigned char attach_compl[] = {
584 0x08, 0x03
585 };
586
587 /* DTAP - Routing Area Update Request */
588 static const unsigned char ra_upd_req[] = {
589 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
590 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
591 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
592 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
593 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
594 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
595 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
596 };
597
598 /* DTAP - Routing Area Update Complete */
599 static const unsigned char ra_upd_complete[] = {
600 0x08, 0x0a
601 };
602
603 /* DTAP - Detach Request (MO) */
604 /* normal detach, power_off = 1 */
605 static const unsigned char detach_req[] = {
606 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
607 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
608 };
609
610 sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
611
612 printf("Testing P-TMSI allocation\n");
613
614 printf(" - sgsn_alloc_ptmsi\n");
615
616 /* reset the PRNG used by sgsn_alloc_ptmsi */
617 srand(1);
618
619 ptmsi1 = sgsn_alloc_ptmsi();
620 OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI);
621
622 ptmsi2 = sgsn_alloc_ptmsi();
623 OSMO_ASSERT(ptmsi2 != GSM_RESERVED_TMSI);
624
625 OSMO_ASSERT(ptmsi1 != ptmsi2);
626
627 printf(" - Repeated Attach Request\n");
628
629 /* reset the PRNG, so that the same P-TMSI will be generated
630 * again */
631 srand(1);
632
633 foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
634
635 /* Create a LLE/LLME */
636 OSMO_ASSERT(count(gprs_llme_list()) == 0);
637 lle = gprs_lle_get_or_create(foreign_tlli, 3);
638 OSMO_ASSERT(count(gprs_llme_list()) == 1);
639
640 /* inject the attach request */
641 send_0408_message(lle->llme, foreign_tlli,
642 attach_req, ARRAY_SIZE(attach_req));
643
644 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
645 OSMO_ASSERT(ctx != NULL);
646 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
647 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
648
649 old_ptmsi = ctx->p_tmsi_old;
650
651 /* we expect an identity request (IMEI) */
652 OSMO_ASSERT(sgsn_tx_counter == 1);
653
654 /* inject the identity response (IMEI) */
655 send_0408_message(ctx->llme, foreign_tlli,
656 ident_resp_imei, ARRAY_SIZE(ident_resp_imei));
657
658 /* check that the MM context has not been removed due to a failed
659 * authorization */
660 OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
661
662 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
663 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
664
665 /* we expect an attach accept */
666 OSMO_ASSERT(sgsn_tx_counter == 1);
667
668 /* we ignore this and send the attach again */
669 send_0408_message(lle->llme, foreign_tlli,
670 attach_req, ARRAY_SIZE(attach_req));
671
672 /* the allocated P-TMSI should be the same */
673 ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
674 OSMO_ASSERT(ctx != NULL);
675 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
676 OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi);
677 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
678
679 /* inject the attach complete */
680 local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL);
681 send_0408_message(ctx->llme, local_tlli,
682 attach_compl, ARRAY_SIZE(attach_compl));
683
684 /* we don't expect a response */
685 OSMO_ASSERT(sgsn_tx_counter == 0);
686
687 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
688 OSMO_ASSERT(ctx->p_tmsi_old == 0);
689 OSMO_ASSERT(ctx->p_tmsi == ptmsi1);
690
691 printf(" - Repeated RA Update Request\n");
692
693 /* inject the RA update request */
694 send_0408_message(ctx->llme, local_tlli,
695 ra_upd_req, ARRAY_SIZE(ra_upd_req));
696
697 /* we expect an RA update accept */
698 OSMO_ASSERT(sgsn_tx_counter == 1);
699
700 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
701 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
702 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
703
704 /* repeat the RA update request */
705 send_0408_message(ctx->llme, local_tlli,
706 ra_upd_req, ARRAY_SIZE(ra_upd_req));
707
708 /* we expect an RA update accept */
709 OSMO_ASSERT(sgsn_tx_counter == 1);
710
711 OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT);
712 OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1);
713 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
714
715 /* inject the RA update complete */
716 local_tlli = gprs_tmsi2tlli(ptmsi2, TLLI_LOCAL);
717 send_0408_message(ctx->llme, local_tlli,
718 ra_upd_complete, ARRAY_SIZE(ra_upd_complete));
719
720 /* we don't expect a response */
721 OSMO_ASSERT(sgsn_tx_counter == 0);
722
723 OSMO_ASSERT(ctx->mm_state == GMM_REGISTERED_NORMAL);
724 OSMO_ASSERT(ctx->p_tmsi_old == 0);
725 OSMO_ASSERT(ctx->p_tmsi == ptmsi2);
726
727 /* inject the detach */
728 send_0408_message(ctx->llme, local_tlli,
729 detach_req, ARRAY_SIZE(detach_req));
730
731 /* verify that things are gone */
732 OSMO_ASSERT(count(gprs_llme_list()) == 0);
733 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
734 OSMO_ASSERT(!ictx);
735
736 sgsn->cfg.auth_policy = saved_auth_policy;
737}
738
739
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200740static struct log_info_cat gprs_categories[] = {
741 [DMM] = {
742 .name = "DMM",
743 .description = "Layer3 Mobility Management (MM)",
744 .color = "\033[1;33m",
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100745 .enabled = 1, .loglevel = LOGL_DEBUG,
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200746 },
747 [DPAG] = {
748 .name = "DPAG",
749 .description = "Paging Subsystem",
750 .color = "\033[1;38m",
751 .enabled = 1, .loglevel = LOGL_NOTICE,
752 },
753 [DMEAS] = {
754 .name = "DMEAS",
755 .description = "Radio Measurement Processing",
756 .enabled = 0, .loglevel = LOGL_NOTICE,
757 },
758 [DREF] = {
759 .name = "DREF",
760 .description = "Reference Counting",
761 .enabled = 0, .loglevel = LOGL_NOTICE,
762 },
763 [DGPRS] = {
764 .name = "DGPRS",
765 .description = "GPRS Packet Service",
766 .enabled = 1, .loglevel = LOGL_DEBUG,
767 },
768 [DNS] = {
769 .name = "DNS",
770 .description = "GPRS Network Service (NS)",
771 .enabled = 1, .loglevel = LOGL_INFO,
772 },
773 [DBSSGP] = {
774 .name = "DBSSGP",
775 .description = "GPRS BSS Gateway Protocol (BSSGP)",
776 .enabled = 1, .loglevel = LOGL_DEBUG,
777 },
778 [DLLC] = {
779 .name = "DLLC",
780 .description = "GPRS Logical Link Control Protocol (LLC)",
781 .enabled = 1, .loglevel = LOGL_DEBUG,
782 },
783 [DSNDCP] = {
784 .name = "DSNDCP",
785 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
786 .enabled = 1, .loglevel = LOGL_DEBUG,
787 },
788};
789
790static struct log_info info = {
791 .cat = gprs_categories,
792 .num_cat = ARRAY_SIZE(gprs_categories),
793};
794
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +0200795int main(int argc, char **argv)
796{
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200797 osmo_init_logging(&info);
798 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
799 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
800
Jacob Erlbeckb2acd742014-11-13 10:48:39 +0100801 sgsn_auth_init();
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100802
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200803 test_llme();
Holger Hans Peter Freyther94246842014-10-02 22:24:47 +0200804 test_gmm_detach();
Jacob Erlbeck0b2da872014-10-27 14:34:13 +0100805 test_gmm_detach_power_off();
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200806 test_gmm_detach_no_mmctx();
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +0100807 test_gmm_status_no_mmctx();
Jacob Erlbeck7c24b3e2014-10-29 12:11:58 +0100808 test_gmm_attach();
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +0100809 test_gmm_reject();
Jacob Erlbecke06476a2014-11-06 15:43:10 +0100810 test_gmm_ptmsi_allocation();
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200811 printf("Done\n");
Holger Hans Peter Freyther232f6212014-09-30 09:10:25 +0200812 return 0;
813}
Holger Hans Peter Freyther49dbcd92014-10-02 21:27:24 +0200814
815
816/* stubs */
817struct osmo_prim_hdr;
818int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
819{
820 abort();
821}