blob: ed30af8de0ad07f5926e2dbde5037e519d44022d [file] [log] [blame]
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001/* test routines for gbproxy
2 * send NS messages to the gbproxy and dumps what happens
3 * (C) 2013 by sysmocom s.f.m.c. GmbH
4 * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
5 */
6
7#undef _GNU_SOURCE
8#define _GNU_SOURCE
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <string.h>
14#include <getopt.h>
15#include <dlfcn.h>
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020016#include <time.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020017#include <sys/types.h>
18#include <sys/socket.h>
19
20#include <osmocom/core/msgb.h>
21#include <osmocom/core/application.h>
22#include <osmocom/core/utils.h>
23#include <osmocom/core/logging.h>
24#include <osmocom/core/talloc.h>
25#include <osmocom/core/signal.h>
26#include <osmocom/core/rate_ctr.h>
Jacob Erlbeckb1381062014-07-01 12:41:13 +020027#include <osmocom/gsm/tlv.h>
Jacob Erlbeck59748e62014-08-11 17:26:21 +020028#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020029#include <osmocom/gprs/gprs_msgb.h>
30#include <osmocom/gprs/gprs_ns.h>
31#include <osmocom/gprs/gprs_bssgp.h>
32
33#include <openbsc/gb_proxy.h>
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020034#include <openbsc/gprs_utils.h>
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +020035#include <openbsc/gprs_llc.h>
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020036#include <openbsc/debug.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020037
38#define REMOTE_BSS_ADDR 0x01020304
39#define REMOTE_SGSN_ADDR 0x05060708
40
Jacob Erlbeck2082afa2013-10-18 13:04:47 +020041#define SGSN_NSEI 0x0100
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020042
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020043struct gbproxy_config gbcfg = {0};
44
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020045static int dump_global(FILE *stream, int indent)
46{
47 unsigned int i;
48 const struct rate_ctr_group_desc *desc;
49 int rc;
50
51 rc = fprintf(stream, "%*sGbproxy global:\n", indent, "");
52 if (rc < 0)
53 return rc;
54
55 desc = gbcfg.ctrg->desc;
56
57 for (i = 0; i < desc->num_ctr; i++) {
58 struct rate_ctr *ctr = &gbcfg.ctrg->ctr[i];
59 if (ctr->current) {
60 rc = fprintf(stream, "%*s %s: %llu\n",
61 indent, "",
62 desc->ctr_desc[i].description,
63 (long long)ctr->current);
64
65 if (rc < 0)
66 return rc;
67 }
68 }
69
70 return 0;
71}
72
Jacob Erlbeck7b821d02014-08-08 08:37:37 +020073static int dump_peers(FILE *stream, int indent, time_t now,
74 struct gbproxy_config *cfg)
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020075{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020076 struct gbproxy_peer *peer;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020077 struct gprs_ra_id raid;
78 unsigned int i;
79 const struct rate_ctr_group_desc *desc;
80 int rc;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020081
82 rc = fprintf(stream, "%*sPeers:\n", indent, "");
83 if (rc < 0)
84 return rc;
85
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +020086 llist_for_each_entry(peer, &cfg->bts_peers, list) {
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020087 struct gbproxy_tlli_info *tlli_info;
88 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020089 gsm48_parse_ra(&raid, peer->ra);
90
91 rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, "
92 "RAI %u-%u-%u-%u\n",
93 indent, "",
94 peer->nsei, peer->bvci,
95 peer->blocked ? "" : "not ",
96 raid.mcc, raid.mnc, raid.lac, raid.rac);
97
98 if (rc < 0)
99 return rc;
100
101 desc = peer->ctrg->desc;
102
103 for (i = 0; i < desc->num_ctr; i++) {
104 struct rate_ctr *ctr = &peer->ctrg->ctr[i];
105 if (ctr->current) {
106 rc = fprintf(stream, "%*s %s: %llu\n",
107 indent, "",
108 desc->ctr_desc[i].description,
109 (long long)ctr->current);
110
111 if (rc < 0)
112 return rc;
113 }
114 }
115
116 fprintf(stream, "%*s TLLI-Cache: %d\n",
117 indent, "", state->enabled_tllis_count);
118 llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
119 char mi_buf[200];
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200120 time_t age = now ? now - tlli_info->timestamp : 0;
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200121 if (tlli_info->mi_data_len > 0) {
122 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
123 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
124 tlli_info->mi_data,
125 tlli_info->mi_data_len);
126 } else {
127 snprintf(mi_buf, sizeof(mi_buf), "(none)");
128 }
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200129 fprintf(stream, "%*s TLLI %08x",
130 indent, "", tlli_info->tlli);
131 if (tlli_info->assigned_tlli)
132 fprintf(stream, "/%08x", tlli_info->assigned_tlli);
133 rc = fprintf(stream, ", IMSI %s, AGE %d\n",
134 mi_buf, (int)age);
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200135 if (rc < 0)
136 return rc;
137 }
138 }
139
140 return 0;
141}
142
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200143/* DTAP - Attach Request */
144static const unsigned char dtap_attach_req[] = {
145 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
146 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22,
147 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
148 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
149 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
150 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200151};
152
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200153/* DTAP - Identity Request */
154static const unsigned char dtap_identity_req[] = {
155 0x08, 0x15, 0x01
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200156};
157
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200158/* DTAP - Identity Response */
159static const unsigned char dtap_identity_resp[] = {
160 0x08, 0x16, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15,
161 0x16, 0x17, 0x18
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200162};
163
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200164/* DTAP - Attach Accept */
165static const unsigned char dtap_attach_acc[] = {
166 0x08, 0x02, 0x01, 0x49, 0x04, 0x21, 0x63, 0x54,
167 0x40, 0x50, 0x60, 0x19, 0xcd, 0xd7, 0x08, 0x17,
168 0x16, 0x18, 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200169};
170
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200171/* DTAP - Attach Complete */
172static const unsigned char dtap_attach_complete[] = {
173 0x08, 0x03
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200174};
175
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200176/* DTAP - GMM Information */
177static const unsigned char dtap_gmm_information[] = {
178 0x08, 0x21
Jacob Erlbeck11669742014-06-06 18:47:36 +0200179};
180
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200181/* DTAP - Routing Area Update Request */
182static const unsigned char dtap_ra_upd_req[] = {
183 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
184 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
185 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
186 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
187 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
188 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
189 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200190};
191
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200192/* DTAP - Routing Area Update Accept */
193static const unsigned char dtap_ra_upd_acc[] = {
194 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
195 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
196 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x17, 0x16,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200197};
198
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200199/* DTAP - Activate PDP Context Request */
200static const unsigned char dtap_act_pdp_ctx_req[] = {
201 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200202 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
204 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
205 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
206 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200207 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200208};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200209
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200210/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200211/* normal detach, power_off = 1 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200212static const unsigned char dtap_detach_po_req[] = {
213 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
214 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200215};
216
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200217/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200218/* normal detach, power_off = 0 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200219static const unsigned char dtap_detach_req[] = {
220 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
221 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200222};
223
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200224/* DTAP - Detach Accept */
225static const unsigned char dtap_detach_acc[] = {
226 0x08, 0x06, 0x00
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200227};
228
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200229static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
230 struct sockaddr_in *peer, const unsigned char* data,
231 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200232
233static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
234 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
235{
236 /* GPRS Network Service, PDU type: NS_RESET,
237 */
238 unsigned char msg[12] = {
239 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
240 0x04, 0x82, 0x11, 0x22
241 };
242
243 msg[3] = cause;
244 msg[6] = nsvci / 256;
245 msg[7] = nsvci % 256;
246 msg[10] = nsei / 256;
247 msg[11] = nsei % 256;
248
249 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
250}
251
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200252static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
253 uint16_t nsvci, uint16_t nsei)
254{
255 /* GPRS Network Service, PDU type: NS_RESET_ACK,
256 */
257 unsigned char msg[9] = {
258 0x03, 0x01, 0x82, 0x11, 0x22,
259 0x04, 0x82, 0x11, 0x22
260 };
261
262 msg[3] = nsvci / 256;
263 msg[4] = nsvci % 256;
264 msg[7] = nsei / 256;
265 msg[8] = nsei % 256;
266
267 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
268}
269
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200270static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
271{
272 /* GPRS Network Service, PDU type: NS_ALIVE */
273 unsigned char msg[1] = {
274 0x0a
275 };
276
277 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
278}
279
280static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
281{
282 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
283 unsigned char msg[1] = {
284 0x0b
285 };
286
287 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
288}
289
290static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
291{
292 /* GPRS Network Service, PDU type: NS_UNBLOCK */
293 unsigned char msg[1] = {
294 0x06
295 };
296
297 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
298}
299
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200300static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
301{
302 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
303 unsigned char msg[1] = {
304 0x07
305 };
306
307 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
308}
309
310static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
311 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200312 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
313{
314 /* GPRS Network Service, PDU type: NS_UNITDATA */
315 unsigned char msg[4096] = {
316 0x00, 0x00, 0x00, 0x00
317 };
318
319 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
320
321 msg[2] = nsbvci / 256;
322 msg[3] = nsbvci % 256;
323 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
324
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200325 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200326}
327
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200328static void send_bssgp_ul_unitdata(
329 struct gprs_ns_inst *nsi, const char *text,
330 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
331 struct gprs_ra_id *raid, uint16_t cell_id,
332 const uint8_t *llc_msg, size_t llc_msg_size)
333{
334 /* GPRS Network Service, PDU type: NS_UNITDATA */
335 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
336 unsigned char msg[4096] = {
337 0x01, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
338 0x08, 0x88, /* RAI */ 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
339 /* CELL ID */ 0x00, 0x00, 0x00, 0x80, 0x0e, /* LLC LEN */ 0x00, 0x00,
340 };
341
342 size_t bssgp_msg_size = 23 + llc_msg_size;
343
344 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg));
345
346 gsm48_construct_ra(msg + 10, raid);
347 msg[1] = (uint8_t)(tlli >> 24);
348 msg[2] = (uint8_t)(tlli >> 16);
349 msg[3] = (uint8_t)(tlli >> 8);
350 msg[4] = (uint8_t)(tlli >> 0);
351 msg[16] = cell_id / 256;
352 msg[17] = cell_id % 256;
353 msg[21] = llc_msg_size / 256;
354 msg[22] = llc_msg_size % 256;
355 memcpy(msg + 23, llc_msg, llc_msg_size);
356
357 send_ns_unitdata(nsi, text ? text : "BSSGP UL UNITDATA",
358 src_addr, nsbvci, msg, bssgp_msg_size);
359}
360
361static void send_bssgp_dl_unitdata(
362 struct gprs_ns_inst *nsi, const char *text,
363 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
364 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
365 const uint8_t *llc_msg, size_t llc_msg_size)
366{
367 /* Base Station Subsystem GPRS Protocol: DL_UNITDATA */
368 unsigned char msg[4096] = {
369 0x00, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20,
370 0x16, 0x82, 0x02, 0x58,
371 };
372 unsigned char racap_drx[] = {
373 0x13, 0x99, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96,
374 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62,
375 0x00, 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00,
376 0x60, 0x80, 0x00, 0x0a, 0x82, 0x08, 0x02
377 };
378
379 size_t bssgp_msg_size = 0;
380
381 OSMO_ASSERT(51 + imsi_size + llc_msg_size <= sizeof(msg));
382
383 msg[1] = (uint8_t)(tlli >> 24);
384 msg[2] = (uint8_t)(tlli >> 16);
385 msg[3] = (uint8_t)(tlli >> 8);
386 msg[4] = (uint8_t)(tlli >> 0);
387
388 bssgp_msg_size = 12;
389
390 if (with_racap_drx) {
391 memcpy(msg + bssgp_msg_size, racap_drx, sizeof(racap_drx));
392 bssgp_msg_size += sizeof(racap_drx);
393 }
394
395 if (imsi) {
396 OSMO_ASSERT(imsi_size <= 127);
397 msg[bssgp_msg_size] = BSSGP_IE_IMSI;
398 msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
399 memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
400 bssgp_msg_size += 2 + imsi_size;
401 }
402
403 if ((bssgp_msg_size % 4) != 0) {
404 size_t abytes = (4 - (bssgp_msg_size + 2) % 4) % 4;
405 msg[bssgp_msg_size] = BSSGP_IE_ALIGNMENT;
406 msg[bssgp_msg_size + 1] = 0x80 | abytes;
407 memset(msg + bssgp_msg_size + 2, 0, abytes);
408 bssgp_msg_size += 2 + abytes;
409 }
410
411 msg[bssgp_msg_size] = BSSGP_IE_LLC_PDU;
412 if (llc_msg_size < 128) {
413 msg[bssgp_msg_size + 1] = 0x80 | llc_msg_size;
414 bssgp_msg_size += 2;
415 } else {
416 msg[bssgp_msg_size + 1] = llc_msg_size / 256;
417 msg[bssgp_msg_size + 2] = llc_msg_size % 256;
418 bssgp_msg_size += 3;
419 }
420 memcpy(msg + bssgp_msg_size, llc_msg, llc_msg_size);
421 bssgp_msg_size += llc_msg_size;
422
423
424 send_ns_unitdata(nsi, text ? text : "BSSGP DL UNITDATA",
425 src_addr, nsbvci, msg, bssgp_msg_size);
426}
427
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200428static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
429 uint16_t bvci)
430{
431 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
432 * BSSGP RESET */
Jacob Erlbeckda4b4922014-08-06 12:38:10 +0200433 unsigned char msg[18] = {
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200434 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200435 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
436 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200437 };
438
439 msg[3] = bvci / 256;
440 msg[4] = bvci % 256;
441
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200442 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
443}
444
445static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
446 struct sockaddr_in *src_addr, uint16_t bvci)
447{
448 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
449 * BSSGP RESET_ACK */
450 static unsigned char msg[5] = {
451 0x23, 0x04, 0x82, 0x00,
452 0x00
453 };
454
455 msg[3] = bvci / 256;
456 msg[4] = bvci % 256;
457
458 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200459}
460
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200461static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
462 struct sockaddr_in *src_addr,
463 struct gprs_ra_id *raid)
464{
465 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
466 unsigned char msg[15] = {
467 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
468 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
469 };
470
471 gsm48_construct_ra(msg + 9, raid);
472
473 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
474}
475
476static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
477 struct sockaddr_in *src_addr,
478 struct gprs_ra_id *raid)
479{
480 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
481 unsigned char msg[18] = {
482 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
483 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
484 0x81, 0x01
485 };
486
487 gsm48_construct_ra(msg + 9, raid);
488
489 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
490}
491
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200492static void send_llc_ul_ui(
493 struct gprs_ns_inst *nsi, const char *text,
494 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
495 struct gprs_ra_id *raid, uint16_t cell_id,
496 unsigned sapi, unsigned nu,
497 const uint8_t *msg, size_t msg_size)
498{
499 unsigned char llc_msg[4096] = {
500 0x00, 0xc0, 0x01
501 };
502
503 size_t llc_msg_size = 3 + msg_size + 3;
504 uint8_t e_bit = 0;
505 uint8_t pm_bit = 1;
506 unsigned fcs;
507
508 nu &= 0x01ff;
509
510 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
511
512 llc_msg[0] = (sapi & 0x0f);
513 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
514 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
515
516 memcpy(llc_msg + 3, msg, msg_size);
517
518 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
519 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
520 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
521 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
522
523 send_bssgp_ul_unitdata(nsi, text ? text : "LLC UI",
524 src_addr, nsbvci, tlli, raid, cell_id,
525 llc_msg, llc_msg_size);
526}
527
528static void send_llc_dl_ui(
529 struct gprs_ns_inst *nsi, const char *text,
530 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
531 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
532 unsigned sapi, unsigned nu,
533 const uint8_t *msg, size_t msg_size)
534{
535 /* GPRS Network Service, PDU type: NS_UNITDATA */
536 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
537 unsigned char llc_msg[4096] = {
538 0x00, 0x00, 0x01
539 };
540
541 size_t llc_msg_size = 3 + msg_size + 3;
542 uint8_t e_bit = 0;
543 uint8_t pm_bit = 1;
544 unsigned fcs;
545
546 nu &= 0x01ff;
547
548 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
549
550 llc_msg[0] = 0x40 | (sapi & 0x0f);
551 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
552 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
553
554 memcpy(llc_msg + 3, msg, msg_size);
555
556 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
557 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
558 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
559 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
560
561 send_bssgp_dl_unitdata(nsi, text ? text : "LLC UI",
562 src_addr, nsbvci, tlli,
563 with_racap_drx, imsi, imsi_size,
564 llc_msg, llc_msg_size);
565}
566
567
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200568static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
569 uint16_t nsvci, uint16_t nsei)
570{
571 printf("Setup NS-VC: remote 0x%08x:%d, "
572 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
573 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
574 nsvci, nsvci, nsei, nsei);
575
576 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
577 send_ns_alive(nsi, src_addr);
578 send_ns_unblock(nsi, src_addr);
579 send_ns_alive_ack(nsi, src_addr);
580}
581
582static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
583 uint16_t bvci)
584{
585 printf("Setup BSSGP: remote 0x%08x:%d, "
586 "BVCI 0x%04x(%d)\n\n",
587 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
588 bvci, bvci);
589
590 send_bssgp_reset(nsi, src_addr, bvci);
591}
592
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200593static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
594{
595 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
596 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
597 send_ns_alive_ack(nsi, sgsn_peer);
598 send_ns_unblock_ack(nsi, sgsn_peer);
599 send_ns_alive(nsi, sgsn_peer);
600}
601
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200602static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
603{
604 sgsn_peer->sin_family = AF_INET;
605 sgsn_peer->sin_port = htons(32000);
606 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
607}
608
609static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
610{
611 size_t i;
612
613 for (i = 0; i < size; ++i) {
614 bss_peers[i].sin_family = AF_INET;
615 bss_peers[i].sin_port = htons((i + 1) * 1111);
616 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
617 }
618}
619
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200620int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
621 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
622
623/* override */
624int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
625 struct msgb *msg, uint16_t bvci)
626{
627 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
628 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200629 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200630
631 switch (event) {
632 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200633 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200634 default:
635 break;
636 }
637 return 0;
638}
639
640/* override */
641ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
642 const struct sockaddr *dest_addr, socklen_t addrlen)
643{
644 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
645 const struct sockaddr *, socklen_t);
646 static sendto_t real_sendto = NULL;
647 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200648 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200649
650 if (!real_sendto)
651 real_sendto = dlsym(RTLD_NEXT, "sendto");
652
653 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200654 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
655 dest_host, dest_port,
656 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200657 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200658 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
659 dest_host, dest_port,
660 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200661 else
662 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
663
664 return len;
665}
666
667/* override */
668int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
669{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200670 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
671 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200672 uint16_t bvci = msgb_bvci(msg);
673 uint16_t nsei = msgb_nsei(msg);
674
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200675 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200676
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200677 if (!real_gprs_ns_sendmsg)
678 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
679
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200680 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200681 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
682 "msg length %d (%s)\n",
683 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200684 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200685 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
686 "msg length %d (%s)\n",
687 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200688
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200689 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200690}
691
692static void dump_rate_ctr_group(FILE *stream, const char *prefix,
693 struct rate_ctr_group *ctrg)
694{
695 unsigned int i;
696
697 for (i = 0; i < ctrg->desc->num_ctr; i++) {
698 struct rate_ctr *ctr = &ctrg->ctr[i];
699 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
700 fprintf(stream, " %s%s: %llu%s",
701 prefix, ctrg->desc->ctr_desc[i].description,
702 (long long)ctr->current,
703 "\n");
704 };
705}
706
707/* Signal handler for signals from NS layer */
708static int test_signal(unsigned int subsys, unsigned int signal,
709 void *handler_data, void *signal_data)
710{
711 struct ns_signal_data *nssd = signal_data;
712 int rc;
713
714 if (subsys != SS_L_NS)
715 return 0;
716
717 switch (signal) {
718 case S_NS_RESET:
719 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
720 nssd->nsvc->nsvci,
721 gprs_ns_ll_str(nssd->nsvc));
722 break;
723
724 case S_NS_ALIVE_EXP:
725 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
726 nssd->nsvc->nsvci,
727 gprs_ns_ll_str(nssd->nsvc));
728 break;
729
730 case S_NS_BLOCK:
731 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
732 nssd->nsvc->nsvci,
733 gprs_ns_ll_str(nssd->nsvc));
734 break;
735
736 case S_NS_UNBLOCK:
737 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
738 nssd->nsvc->nsvci,
739 gprs_ns_ll_str(nssd->nsvc));
740 break;
741
742 case S_NS_REPLACED:
743 printf("==> got signal NS_REPLACED: 0x%04x/%s",
744 nssd->nsvc->nsvci,
745 gprs_ns_ll_str(nssd->nsvc));
746 printf(" -> 0x%04x/%s\n",
747 nssd->old_nsvc->nsvci,
748 gprs_ns_ll_str(nssd->old_nsvc));
749 break;
750
751 default:
752 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
753 nssd->nsvc->nsvci,
754 gprs_ns_ll_str(nssd->nsvc));
755 break;
756 }
757 printf("\n");
758 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
759 return rc;
760}
761
762static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
763{
764 struct msgb *msg;
765 int ret;
766 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
767 fprintf(stderr, "message too long: %d\n", data_len);
768 return -1;
769 }
770
771 msg = gprs_ns_msgb_alloc();
772 memmove(msg->data, data, data_len);
773 msg->l2h = msg->data;
774 msgb_put(msg, data_len);
775
776 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
777 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
778 osmo_hexdump(data, data_len));
779
780 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
781
782 printf("result (%s) = %d\n\n", text, ret);
783
784 msgb_free(msg);
785
786 return ret;
787}
788
789static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
790{
791 struct gprs_nsvc *nsvc;
792
793 printf("Current NS-VCIs:\n");
794 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
795 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200796 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200797 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200798 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
799 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
800 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200801 );
802 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
803 }
804 printf("\n");
805}
806
807static void test_gbproxy()
808{
809 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
810 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200811 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200812
813 bssgp_nsi = nsi;
814 gbcfg.nsi = bssgp_nsi;
815 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
816
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200817 configure_sgsn_peer(&sgsn_peer);
818 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200819
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200820 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200821 printf("--- Initialise SGSN ---\n\n");
822
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200823 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200824 gprs_dump_nsi(nsi);
825
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200826 printf("--- Initialise BSS 1 ---\n\n");
827
828 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
829 setup_bssgp(nsi, &bss_peer[0], 0x1002);
830 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200831 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200832
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200833 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
834
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200835 printf("--- Initialise BSS 2 ---\n\n");
836
837 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
838 setup_bssgp(nsi, &bss_peer[1], 0x2002);
839 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200840 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200841
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200842 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
843
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200844 printf("--- Move BSS 1 to new port ---\n\n");
845
846 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
847 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200848 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200849
850 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
851
852 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
853 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200854 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200855
856 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
857
858 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
859 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200860 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200861
862 printf("--- Move BSS 2 to new port ---\n\n");
863
864 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
865 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200866 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200867
868 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
869
870 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
871 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200872 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200873
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200874 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
875
876 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
877 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200878 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200879
880 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
881
882 setup_bssgp(nsi, &bss_peer[0], 0x1012);
883 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200884 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200885
886 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
887
888 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
889
890 setup_bssgp(nsi, &bss_peer[0], 0x1002);
891 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200892 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200893
894 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
895
896 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
897
898 setup_bssgp(nsi, &bss_peer[0], 0x1002);
899 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200900 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200901
902 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
903
904 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
905
906 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
907
908 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
909
910 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
911
912 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
913
914 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
915
916 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
917
918 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
919
920 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
921
922 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
923
924 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
925
926 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
927
928 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
929
930 setup_bssgp(nsi, &bss_peer[2], 0x1002);
931 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200932 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200933
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200934 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200935
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200936 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
937
938 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
939
940 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
941
942 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
943
944 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
945
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200946 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
947
948 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
949
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200950 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200951
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200952 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200953 gprs_ns_destroy(nsi);
954 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200955}
956
957static void test_gbproxy_ident_changes()
958{
959 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
960 struct sockaddr_in bss_peer[1] = {{0},};
961 struct sockaddr_in sgsn_peer= {0};
962 uint16_t nsei[2] = {0x1000, 0x2000};
963 uint16_t nsvci[2] = {0x1001, 0x2001};
964 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
965
966 bssgp_nsi = nsi;
967 gbcfg.nsi = bssgp_nsi;
968 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
969
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200970 configure_sgsn_peer(&sgsn_peer);
971 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200972
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200973 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200974 printf("--- Initialise SGSN ---\n\n");
975
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200976 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200977 gprs_dump_nsi(nsi);
978
979 printf("--- Initialise BSS 1 ---\n\n");
980
981 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
982 gprs_dump_nsi(nsi);
983
984 printf("--- Setup BVCI 1 ---\n\n");
985
986 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
987 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200988 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200989
990 printf("--- Setup BVCI 2 ---\n\n");
991
992 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
993 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200994 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200995
996 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
997
998 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
999 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1000
1001 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
1002
1003 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
1004 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
1005
1006 printf("--- Change NSEI ---\n\n");
1007
1008 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
1009 gprs_dump_nsi(nsi);
1010
1011 printf("--- Setup BVCI 1 ---\n\n");
1012
1013 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1014 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001015 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001016
1017 printf("--- Setup BVCI 3 ---\n\n");
1018
1019 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
1020 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001021 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001022
1023 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1024
1025 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1026 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1027
1028 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1029 " (should fail) ---\n\n");
1030
1031 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001032 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001033 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001034 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001035
1036 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1037
1038 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1039 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1040
1041 printf("--- Change NSVCI ---\n\n");
1042
1043 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
1044 gprs_dump_nsi(nsi);
1045
1046 printf("--- Setup BVCI 1 ---\n\n");
1047
1048 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1049 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001050 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001051
1052 printf("--- Setup BVCI 4 ---\n\n");
1053
1054 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
1055 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001056 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001057
1058 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1059
1060 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1061 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1062
1063 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1064 " (should fail) ---\n\n");
1065
1066 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001067 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001068 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001069 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001070
1071 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1072
1073 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1074 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1075
1076 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
1077
1078 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
1079 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
1080
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001081 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001082 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001083
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001084 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001085 gprs_ns_destroy(nsi);
1086 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001087}
1088
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001089static void test_gbproxy_ra_patching()
1090{
1091 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1092 struct sockaddr_in bss_peer[1] = {{0},};
1093 struct sockaddr_in sgsn_peer= {0};
1094 struct gprs_ra_id rai_bss =
1095 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1096 struct gprs_ra_id rai_sgsn =
1097 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
1098 struct gprs_ra_id rai_unknown =
1099 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001100 uint16_t cell_id = 0x7530;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001101 const char *err_msg = NULL;
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001102 const uint32_t ptmsi = 0xefe2b700;
1103 const uint32_t local_tlli = 0xefe2b700;
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001104 const uint32_t foreign_tlli = 0xbbc54679;
1105 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001106 struct gbproxy_tlli_info *tlli_info;
1107 struct gbproxy_peer *peer;
1108
1109 OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001110
1111 bssgp_nsi = nsi;
1112 gbcfg.nsi = bssgp_nsi;
1113 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +02001114 gbcfg.core_mcc = 123;
1115 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +02001116 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +02001117 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001118
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001119 configure_sgsn_peer(&sgsn_peer);
1120 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001121
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001122 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Holger Hans Peter Freyther3fa26442014-08-04 16:27:11 +02001123 if (gbprox_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001124 fprintf(stderr, "Failed to compile RE '%s': %s\n",
1125 gbcfg.match_re, err_msg);
1126 exit(1);
1127 }
1128
1129
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001130 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001131 printf("--- Initialise SGSN ---\n\n");
1132
1133 connect_sgsn(nsi, &sgsn_peer);
1134 gprs_dump_nsi(nsi);
1135
1136 printf("--- Initialise BSS 1 ---\n\n");
1137
1138 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1139 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1140 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001141 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001142
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001143 peer = gbprox_peer_by_nsei(&gbcfg, 0x1000);
1144 OSMO_ASSERT(peer != NULL);
1145
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001146 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1147
1148 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
1149 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
1150
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001151 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001152 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001153
1154 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1155
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001156 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1157 foreign_tlli, &rai_bss, cell_id,
1158 GPRS_SAPI_GMM, 0,
1159 dtap_attach_req, sizeof(dtap_attach_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001160
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001161 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1162 foreign_tlli, 0, NULL, 0,
1163 GPRS_SAPI_GMM, 0,
1164 dtap_identity_req, sizeof(dtap_identity_req));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001165
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001166 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1167 foreign_tlli, &rai_bss, cell_id,
1168 GPRS_SAPI_GMM, 3,
1169 dtap_identity_resp, sizeof(dtap_identity_resp));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001170
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001171 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1172 foreign_tlli, 1, imsi, sizeof(imsi),
1173 GPRS_SAPI_GMM, 1,
1174 dtap_attach_acc, sizeof(dtap_attach_acc));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001175
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001176 tlli_info = gbprox_find_tlli(peer, local_tlli);
1177 OSMO_ASSERT(tlli_info);
1178 OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
1179 OSMO_ASSERT(tlli_info->tlli != local_tlli);
1180 OSMO_ASSERT(!tlli_info->bss_validated);
1181 OSMO_ASSERT(!tlli_info->net_validated);
1182
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001183 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1184 local_tlli, &rai_bss, cell_id,
1185 GPRS_SAPI_GMM, 4,
1186 dtap_attach_complete, sizeof(dtap_attach_complete));
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001187
1188 tlli_info = gbprox_find_tlli(peer, local_tlli);
1189 OSMO_ASSERT(tlli_info);
1190 OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
1191 OSMO_ASSERT(tlli_info->tlli != local_tlli);
1192 OSMO_ASSERT(tlli_info->bss_validated);
1193 OSMO_ASSERT(!tlli_info->net_validated);
1194
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001195 /* Replace APN (1) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001196 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1197 local_tlli, &rai_bss, cell_id,
1198 GPRS_SAPI_GMM, 3,
1199 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001200
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001201 tlli_info = gbprox_find_tlli(peer, local_tlli);
1202 OSMO_ASSERT(tlli_info);
1203 OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
1204 OSMO_ASSERT(tlli_info->tlli != local_tlli);
1205 OSMO_ASSERT(tlli_info->bss_validated);
1206 OSMO_ASSERT(!tlli_info->net_validated);
1207
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001208 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1209 local_tlli, 1, imsi, sizeof(imsi),
1210 GPRS_SAPI_GMM, 2,
1211 dtap_gmm_information, sizeof(dtap_gmm_information));
Jacob Erlbeck11669742014-06-06 18:47:36 +02001212
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001213 tlli_info = gbprox_find_tlli(peer, local_tlli);
1214 OSMO_ASSERT(tlli_info);
1215 OSMO_ASSERT(tlli_info->assigned_tlli == 0);
1216 OSMO_ASSERT(tlli_info->tlli == local_tlli);
1217
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001218 /* Replace APN (2) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001219 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1220 local_tlli, &rai_bss, cell_id,
1221 GPRS_SAPI_GMM, 3,
1222 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001223
Jacob Erlbeck73685282014-05-23 20:48:07 +02001224 gbcfg.core_apn[0] = 0;
1225 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001226
1227 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001228 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1229 local_tlli, &rai_bss, cell_id,
1230 GPRS_SAPI_GMM, 3,
1231 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001232
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001233 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001234
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001235 /* Detach */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001236 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1237 local_tlli, &rai_bss, cell_id,
1238 GPRS_SAPI_GMM, 6,
1239 dtap_detach_req, sizeof(dtap_detach_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001240
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001241 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1242 local_tlli, 1, imsi, sizeof(imsi),
1243 GPRS_SAPI_GMM, 5,
1244 dtap_detach_acc, sizeof(dtap_detach_acc));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001245
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001246 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001247
1248 printf("--- RA update ---\n\n");
1249
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001250 send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1251 foreign_tlli, &rai_bss, 0x7080,
1252 GPRS_SAPI_GMM, 5,
1253 dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001254
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001255 send_llc_dl_ui(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1256 foreign_tlli, 1, imsi, sizeof(imsi),
1257 GPRS_SAPI_GMM, 6,
1258 dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001259
1260 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001261 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1262 local_tlli, &rai_bss, cell_id,
1263 GPRS_SAPI_GMM, 3,
1264 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001265
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001266 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001267
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +02001268 /* Detach (power off -> no Detach Accept) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001269 send_llc_ul_ui(nsi, "DETACH REQ (PWR OFF)", &bss_peer[0], 0x1002,
1270 local_tlli, &rai_bss, cell_id,
1271 GPRS_SAPI_GMM, 6,
1272 dtap_detach_po_req, sizeof(dtap_detach_po_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001273
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001274 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001275 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001276
1277 printf("--- Bad cases ---\n\n");
1278
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001279 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001280 send_llc_ul_ui(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1281 local_tlli, &rai_bss, cell_id,
1282 GPRS_SAPI_GMM, 3,
1283 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001284
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001285 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001286 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1287
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001288 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001289 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001290
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001291 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001292 gprs_ns_destroy(nsi);
1293 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001294}
1295
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001296/* TODO: Move tlv testing to libosmocore */
1297int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1298int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1299 uint8_t **value);
1300int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1301 size_t *value_len);
1302int lv_shift(uint8_t **data, size_t *data_len,
1303 uint8_t **value, size_t *value_len);
1304
1305static void check_tlv_match(uint8_t **data, size_t *data_len,
1306 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1307{
1308 uint8_t *value;
1309 size_t value_len;
1310 int rc;
1311
1312 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1313 OSMO_ASSERT(rc == 0);
1314
1315 rc = tlv_match(data, data_len, tag, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001316 OSMO_ASSERT(rc == (int)value_len + 2);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001317 OSMO_ASSERT(value_len == exp_len);
1318 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1319}
1320
1321static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1322 uint8_t tag, size_t len, const uint8_t *exp_val)
1323{
1324 uint8_t *value;
1325 int rc;
1326
1327 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1328 OSMO_ASSERT(rc == 0);
1329
1330 rc = tv_fixed_match(data, data_len, tag, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001331 OSMO_ASSERT(rc == (int)len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001332 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1333}
1334
1335static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1336 size_t len, const uint8_t *exp_val)
1337{
1338 uint8_t *value;
1339 int rc;
1340
1341 rc = v_fixed_shift(data, data_len, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001342 OSMO_ASSERT(rc == (int)len);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001343 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1344}
1345
1346static void check_lv_shift(uint8_t **data, size_t *data_len,
1347 size_t exp_len, const uint8_t *exp_val)
1348{
1349 uint8_t *value;
1350 size_t value_len;
1351 int rc;
1352
1353 rc = lv_shift(data, data_len, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001354 OSMO_ASSERT(rc == (int)value_len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001355 OSMO_ASSERT(value_len == exp_len);
1356 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1357}
1358
1359static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1360 const uint8_t *test_data)
1361{
1362 uint8_t buf[300] = {0};
1363
1364 uint8_t *unchanged_ptr = buf - 1;
1365 size_t unchanged_len = 0xdead;
1366 size_t tmp_data_len = data_len;
1367 uint8_t *value = unchanged_ptr;
1368 size_t value_len = unchanged_len;
1369 uint8_t *data = buf;
1370
1371 OSMO_ASSERT(data_len <= sizeof(buf));
1372
1373 tlv_put(data, tag, len, test_data);
1374 if (data_len < len + 2) {
1375 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1376 tag, &value, &value_len));
1377 OSMO_ASSERT(tmp_data_len == 0);
1378 OSMO_ASSERT(data == buf + data_len);
1379 OSMO_ASSERT(value == unchanged_ptr);
1380 OSMO_ASSERT(value_len == unchanged_len);
1381 } else {
1382 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1383 tag, &value, &value_len));
1384 OSMO_ASSERT(value != unchanged_ptr);
1385 OSMO_ASSERT(value_len != unchanged_len);
1386 }
1387}
1388
1389static void check_tv_fixed_match_data_len(size_t data_len,
1390 uint8_t tag, size_t len,
1391 const uint8_t *test_data)
1392{
1393 uint8_t buf[300] = {0};
1394
1395 uint8_t *unchanged_ptr = buf - 1;
1396 size_t tmp_data_len = data_len;
1397 uint8_t *value = unchanged_ptr;
1398 uint8_t *data = buf;
1399
1400 OSMO_ASSERT(data_len <= sizeof(buf));
1401
1402 tv_fixed_put(data, tag, len, test_data);
1403
1404 if (data_len < len + 1) {
1405 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1406 tag, len, &value));
1407 OSMO_ASSERT(tmp_data_len == 0);
1408 OSMO_ASSERT(data == buf + data_len);
1409 OSMO_ASSERT(value == unchanged_ptr);
1410 } else {
1411 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1412 tag, len, &value));
1413 OSMO_ASSERT(value != unchanged_ptr);
1414 }
1415}
1416
1417static void check_v_fixed_shift_data_len(size_t data_len,
1418 size_t len, const uint8_t *test_data)
1419{
1420 uint8_t buf[300] = {0};
1421
1422 uint8_t *unchanged_ptr = buf - 1;
1423 size_t tmp_data_len = data_len;
1424 uint8_t *value = unchanged_ptr;
1425 uint8_t *data = buf;
1426
1427 OSMO_ASSERT(data_len <= sizeof(buf));
1428
1429 memcpy(data, test_data, len);
1430
1431 if (data_len < len) {
1432 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1433 len, &value));
1434 OSMO_ASSERT(tmp_data_len == 0);
1435 OSMO_ASSERT(data == buf + data_len);
1436 OSMO_ASSERT(value == unchanged_ptr);
1437 } else {
1438 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1439 len, &value));
1440 OSMO_ASSERT(value != unchanged_ptr);
1441 }
1442}
1443
1444static void check_lv_shift_data_len(size_t data_len,
1445 size_t len, const uint8_t *test_data)
1446{
1447 uint8_t buf[300] = {0};
1448
1449 uint8_t *unchanged_ptr = buf - 1;
1450 size_t unchanged_len = 0xdead;
1451 size_t tmp_data_len = data_len;
1452 uint8_t *value = unchanged_ptr;
1453 size_t value_len = unchanged_len;
1454 uint8_t *data = buf;
1455
1456 lv_put(data, len, test_data);
1457 if (data_len < len + 1) {
1458 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1459 &value, &value_len));
1460 OSMO_ASSERT(tmp_data_len == 0);
1461 OSMO_ASSERT(data == buf + data_len);
1462 OSMO_ASSERT(value == unchanged_ptr);
1463 OSMO_ASSERT(value_len == unchanged_len);
1464 } else {
1465 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1466 &value, &value_len));
1467 OSMO_ASSERT(value != unchanged_ptr);
1468 OSMO_ASSERT(value_len != unchanged_len);
1469 }
1470}
1471
1472static void test_tlv_shift_functions()
1473{
1474 uint8_t test_data[1024];
1475 uint8_t buf[1024];
1476 uint8_t *data_end;
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001477 unsigned i, len;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001478 uint8_t *data;
1479 size_t data_len;
1480 const uint8_t tag = 0x1a;
1481
1482 printf("Test shift functions\n");
1483
1484 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1485 test_data[i] = (uint8_t)i;
1486
1487 for (len = 0; len < 256; len++) {
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001488 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001489
1490 memset(buf, 0xee, sizeof(buf));
1491 data_end = data = buf;
1492
1493 for (i = 0; i < iterations; i++) {
1494 data_end = tlv_put(data_end, tag, len, test_data);
1495 data_end = tv_fixed_put(data_end, tag, len, test_data);
1496 /* v_fixed_put */
1497 memcpy(data_end, test_data, len);
1498 data_end += len;
1499 data_end = lv_put(data_end, len, test_data);
1500 }
1501
1502 data_len = data_end - data;
1503 OSMO_ASSERT(data_len <= sizeof(buf));
1504
1505 for (i = 0; i < iterations; i++) {
1506 check_tlv_match(&data, &data_len, tag, len, test_data);
1507 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1508 check_v_fixed_shift(&data, &data_len, len, test_data);
1509 check_lv_shift(&data, &data_len, len, test_data);
1510 }
1511
1512 OSMO_ASSERT(data == data_end);
1513
1514 /* Test at end of data */
1515
1516 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1517 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1518 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1519 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1520
1521 /* Test invalid data_len */
1522 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1523 check_tlv_match_data_len(data_len, tag, len, test_data);
1524 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1525 check_v_fixed_shift_data_len(data_len, len, test_data);
1526 check_lv_shift_data_len(data_len, len, test_data);
1527 }
1528 }
1529}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001530
1531static void test_gbproxy_tlli_expire(void)
1532{
1533 struct gbproxy_config cfg = {0};
1534 struct gbproxy_peer *peer;
1535 const char *err_msg = NULL;
1536 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1537 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001538 const uint8_t imsi3[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0x76, 0xf8 };
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001539 const uint32_t tlli1 = 1234 | 0xc0000000;
1540 const uint32_t tlli2 = 5678 | 0xc0000000;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001541 const uint32_t tlli3 = 3456 | 0xc0000000;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001542 const char *filter_re = ".*";
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001543 time_t now = 1407479214;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001544
1545 printf("Test TLLI info expiry\n\n");
1546
1547 gbproxy_init_config(&cfg);
1548
1549 if (gbprox_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
1550 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1551 err_msg);
1552 OSMO_ASSERT(err_msg == NULL);
1553 }
1554
1555 {
1556 struct gbproxy_tlli_info *tlli_info;
1557
1558 printf("Test TLLI replacement:\n");
1559
1560 cfg.tlli_max_len = 0;
1561 cfg.tlli_max_age = 0;
1562 peer = gbproxy_peer_alloc(&cfg, 20);
1563 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1564
1565 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001566 tlli_info = gbprox_register_tlli(peer, tlli1,
1567 imsi1, ARRAY_SIZE(imsi1), now);
1568 OSMO_ASSERT(tlli_info);
1569 OSMO_ASSERT(tlli_info->tlli == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001570 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1571
1572 /* replace the old entry */
1573 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001574 tlli_info = gbprox_register_tlli(peer, tlli2,
1575 imsi1, ARRAY_SIZE(imsi1), now);
1576 OSMO_ASSERT(tlli_info);
1577 OSMO_ASSERT(tlli_info->tlli == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001578 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1579
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001580 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001581
1582 /* verify that 5678 has survived */
1583 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1584 OSMO_ASSERT(tlli_info);
1585 OSMO_ASSERT(tlli_info->tlli == tlli2);
1586 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1587 OSMO_ASSERT(!tlli_info);
1588
1589 printf("\n");
1590
1591 gbproxy_peer_free(peer);
1592 }
1593
1594 {
1595 struct gbproxy_tlli_info *tlli_info;
1596
1597 printf("Test IMSI replacement:\n");
1598
1599 cfg.tlli_max_len = 0;
1600 cfg.tlli_max_age = 0;
1601 peer = gbproxy_peer_alloc(&cfg, 20);
1602 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1603
1604 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001605 tlli_info = gbprox_register_tlli(peer, tlli1,
1606 imsi1, ARRAY_SIZE(imsi1), now);
1607 OSMO_ASSERT(tlli_info);
1608 OSMO_ASSERT(tlli_info->tlli == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001609 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1610
1611 /* try to replace the old entry */
1612 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001613 tlli_info = gbprox_register_tlli(peer, tlli1,
1614 imsi2, ARRAY_SIZE(imsi2), now);
1615 OSMO_ASSERT(tlli_info);
1616 OSMO_ASSERT(tlli_info->tlli == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001617 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1618
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001619 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001620
1621 /* verify that 5678 has survived */
1622 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1623 OSMO_ASSERT(!tlli_info);
1624 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1625 OSMO_ASSERT(tlli_info);
1626 OSMO_ASSERT(tlli_info->tlli == tlli1);
1627
1628 printf("\n");
1629
1630 gbproxy_peer_free(peer);
1631 }
1632
1633 {
1634 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001635 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001636
1637 printf("Test TLLI expiry, max_len == 1:\n");
1638
1639 cfg.tlli_max_len = 1;
1640 cfg.tlli_max_age = 0;
1641 peer = gbproxy_peer_alloc(&cfg, 20);
1642 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1643
1644 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001645 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001646 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1647
1648 /* replace the old entry */
1649 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001650 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001651 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1652
1653 num_removed = gbprox_remove_stale_tllis(peer, time(NULL) + 2);
1654 OSMO_ASSERT(num_removed == 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001655 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1656
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001657 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001658
1659 /* verify that 5678 has survived */
1660 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1661 OSMO_ASSERT(!tlli_info);
1662 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1663 OSMO_ASSERT(tlli_info);
1664 OSMO_ASSERT(tlli_info->tlli == tlli2);
1665
1666 printf("\n");
1667
1668 gbproxy_peer_free(peer);
1669 }
1670
1671 {
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001672 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001673
1674 printf("Test TLLI expiry, max_age == 1:\n");
1675
1676 cfg.tlli_max_len = 0;
1677 cfg.tlli_max_age = 1;
1678 peer = gbproxy_peer_alloc(&cfg, 20);
1679 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1680
1681 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001682 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001683 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1684
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001685 printf(" Add TLLI 2, IMSI 2 (should not expire after timeout)\n");
1686 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
1687 now + 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001688 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1689
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001690 num_removed = gbprox_remove_stale_tllis(peer, now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001691 OSMO_ASSERT(num_removed == 1);
1692 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1693
1694 dump_peers(stdout, 2, now + 2, &cfg);
1695
1696 printf("\n");
1697
1698 gbproxy_peer_free(peer);
1699 }
1700
1701 {
1702 int num_removed;
1703
1704 printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
1705
1706 cfg.tlli_max_len = 0;
1707 cfg.tlli_max_age = 1;
1708 peer = gbproxy_peer_alloc(&cfg, 20);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001709 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1710
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001711 printf(" Add TLLI 1, IMSI 1 (should expire)\n");
1712 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
1713 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1714
1715 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
1716 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
1717 now + 1);
1718 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1719
1720 printf(" Add TLLI 3, IMSI 3 (should not expire after timeout)\n");
1721 gbprox_register_tlli(peer, tlli3, imsi3, ARRAY_SIZE(imsi3),
1722 now + 2);
1723 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 3);
1724
1725 dump_peers(stdout, 2, now + 2, &cfg);
1726
1727 printf(" Remove stale TLLIs\n");
1728 num_removed = gbprox_remove_stale_tllis(peer, now + 3);
1729 OSMO_ASSERT(num_removed == 2);
1730 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1731
1732 dump_peers(stdout, 2, now + 2, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001733
1734 printf("\n");
1735
1736 gbproxy_peer_free(peer);
1737 }
1738}
1739
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001740static void test_gbproxy_imsi_matching(void)
1741{
1742 struct gbproxy_config cfg = {0};
1743 struct gbproxy_peer *peer;
1744 const char *err_msg = NULL;
1745 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
1746 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1747 const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
1748 const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
1749 const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
1750 const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
1751 const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1752 const char *filter_re1 = ".*";
1753 const char *filter_re2 = "^1234";
1754 const char *filter_re3 = "^4321";
1755 const char *filter_re4_bad = "^12[";
1756
1757 printf("=== Test IMSI/TMSI matching ===\n\n");
1758
1759 gbproxy_init_config(&cfg);
1760 OSMO_ASSERT(cfg.check_imsi == 0);
1761
1762 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
1763 OSMO_ASSERT(cfg.check_imsi == 1);
1764
1765 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1766 OSMO_ASSERT(cfg.check_imsi == 1);
1767
1768 err_msg = NULL;
1769 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
1770 OSMO_ASSERT(err_msg != NULL);
1771 OSMO_ASSERT(cfg.check_imsi == 0);
1772
1773 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1774 OSMO_ASSERT(cfg.check_imsi == 1);
1775
1776 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, NULL, &err_msg) == 0);
1777 OSMO_ASSERT(cfg.check_imsi == 0);
1778
Jacob Erlbeck29805da2014-08-14 08:57:04 +02001779 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1780 OSMO_ASSERT(cfg.check_imsi == 1);
1781
1782 gbprox_clear_patch_filter(&cfg);
1783 OSMO_ASSERT(cfg.check_imsi == 0);
1784
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001785 peer = gbproxy_peer_alloc(&cfg, 20);
1786
1787 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1788 OSMO_ASSERT(cfg.check_imsi == 1);
1789
1790 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
1791 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
1792 /* imsi3_bad contains 0xE and 0xF digits, but the conversion function
1793 * doesn't complain, so gbprox_check_imsi() doesn't return -1 in this
1794 * case. */
1795 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1796 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1797 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1798 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1799 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1800
1801 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
1802 OSMO_ASSERT(cfg.check_imsi == 1);
1803
1804 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
1805 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
1806 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1807 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1808 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1809 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1810 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1811
1812 /* TODO: Check correct length but wrong type with is_mi_tmsi */
1813
1814 gbproxy_peer_free(peer);
1815}
1816
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001817static struct log_info_cat gprs_categories[] = {
1818 [DGPRS] = {
1819 .name = "DGPRS",
1820 .description = "GPRS Packet Service",
1821 .enabled = 1, .loglevel = LOGL_DEBUG,
1822 },
1823 [DNS] = {
1824 .name = "DNS",
1825 .description = "GPRS Network Service (NS)",
1826 .enabled = 1, .loglevel = LOGL_INFO,
1827 },
1828 [DBSSGP] = {
1829 .name = "DBSSGP",
1830 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1831 .enabled = 1, .loglevel = LOGL_DEBUG,
1832 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001833};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001834
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001835static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001836 .cat = gprs_categories,
1837 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001838};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001839
1840int main(int argc, char **argv)
1841{
1842 osmo_init_logging(&info);
1843 log_set_use_color(osmo_stderr_target, 0);
1844 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001845 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001846
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001847 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001848 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1849 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001850
1851 rate_ctr_init(NULL);
1852
1853 setlinebuf(stdout);
1854
1855 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02001856 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001857 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001858 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001859 test_gbproxy_ident_changes();
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001860 test_gbproxy_imsi_matching();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001861 test_gbproxy_ra_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001862 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001863 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001864
1865 exit(EXIT_SUCCESS);
1866}