blob: 2a521eeec37fee36189e985c3a41ac888f49f8ca [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",
Jacob Erlbeck9057bc32014-08-12 16:30:30 +0200130 indent, "", tlli_info->tlli.current);
131 if (tlli_info->tlli.assigned)
132 fprintf(stream, "/%08x", tlli_info->tlli.assigned);
133 if (tlli_info->sgsn_tlli.current) {
134 fprintf(stream, " -> %08x",
135 tlli_info->sgsn_tlli.current);
136 if (tlli_info->sgsn_tlli.assigned)
137 fprintf(stream, "/%08x",
138 tlli_info->sgsn_tlli.assigned);
139 }
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200140 rc = fprintf(stream, ", IMSI %s, AGE %d\n",
141 mi_buf, (int)age);
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200142 if (rc < 0)
143 return rc;
144 }
145 }
146
147 return 0;
148}
149
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200150/* DTAP - Attach Request */
151static const unsigned char dtap_attach_req[] = {
152 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
153 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22,
154 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
155 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
156 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
157 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200158};
159
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200160/* DTAP - Identity Request */
161static const unsigned char dtap_identity_req[] = {
162 0x08, 0x15, 0x01
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200163};
164
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200165/* DTAP - Identity Response */
166static const unsigned char dtap_identity_resp[] = {
167 0x08, 0x16, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15,
168 0x16, 0x17, 0x18
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200169};
170
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200171/* DTAP - Attach Accept */
172static const unsigned char dtap_attach_acc[] = {
173 0x08, 0x02, 0x01, 0x49, 0x04, 0x21, 0x63, 0x54,
174 0x40, 0x50, 0x60, 0x19, 0xcd, 0xd7, 0x08, 0x17,
175 0x16, 0x18, 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200176};
177
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200178/* DTAP - Attach Complete */
179static const unsigned char dtap_attach_complete[] = {
180 0x08, 0x03
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200181};
182
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200183/* DTAP - GMM Information */
184static const unsigned char dtap_gmm_information[] = {
185 0x08, 0x21
Jacob Erlbeck11669742014-06-06 18:47:36 +0200186};
187
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200188/* DTAP - Routing Area Update Request */
189static const unsigned char dtap_ra_upd_req[] = {
190 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
191 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
192 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
193 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
194 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
195 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
196 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200197};
198
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200199/* DTAP - Routing Area Update Accept */
200static const unsigned char dtap_ra_upd_acc[] = {
201 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
202 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
203 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x17, 0x16,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200204};
205
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200206/* DTAP - Activate PDP Context Request */
207static const unsigned char dtap_act_pdp_ctx_req[] = {
208 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200209 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
211 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
212 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
213 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200214 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200215};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200216
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200217/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200218/* normal detach, power_off = 1 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200219static const unsigned char dtap_detach_po_req[] = {
220 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
221 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200222};
223
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200224/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200225/* normal detach, power_off = 0 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200226static const unsigned char dtap_detach_req[] = {
227 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
228 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200229};
230
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200231/* DTAP - Detach Accept */
232static const unsigned char dtap_detach_acc[] = {
233 0x08, 0x06, 0x00
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200234};
235
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200236static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
237 struct sockaddr_in *peer, const unsigned char* data,
238 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200239
240static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
241 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
242{
243 /* GPRS Network Service, PDU type: NS_RESET,
244 */
245 unsigned char msg[12] = {
246 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
247 0x04, 0x82, 0x11, 0x22
248 };
249
250 msg[3] = cause;
251 msg[6] = nsvci / 256;
252 msg[7] = nsvci % 256;
253 msg[10] = nsei / 256;
254 msg[11] = nsei % 256;
255
256 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
257}
258
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200259static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
260 uint16_t nsvci, uint16_t nsei)
261{
262 /* GPRS Network Service, PDU type: NS_RESET_ACK,
263 */
264 unsigned char msg[9] = {
265 0x03, 0x01, 0x82, 0x11, 0x22,
266 0x04, 0x82, 0x11, 0x22
267 };
268
269 msg[3] = nsvci / 256;
270 msg[4] = nsvci % 256;
271 msg[7] = nsei / 256;
272 msg[8] = nsei % 256;
273
274 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
275}
276
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200277static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
278{
279 /* GPRS Network Service, PDU type: NS_ALIVE */
280 unsigned char msg[1] = {
281 0x0a
282 };
283
284 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
285}
286
287static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
288{
289 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
290 unsigned char msg[1] = {
291 0x0b
292 };
293
294 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
295}
296
297static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
298{
299 /* GPRS Network Service, PDU type: NS_UNBLOCK */
300 unsigned char msg[1] = {
301 0x06
302 };
303
304 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
305}
306
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200307static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
308{
309 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
310 unsigned char msg[1] = {
311 0x07
312 };
313
314 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
315}
316
317static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
318 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200319 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
320{
321 /* GPRS Network Service, PDU type: NS_UNITDATA */
322 unsigned char msg[4096] = {
323 0x00, 0x00, 0x00, 0x00
324 };
325
326 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
327
328 msg[2] = nsbvci / 256;
329 msg[3] = nsbvci % 256;
330 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
331
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200332 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200333}
334
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200335static void send_bssgp_ul_unitdata(
336 struct gprs_ns_inst *nsi, const char *text,
337 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
338 struct gprs_ra_id *raid, uint16_t cell_id,
339 const uint8_t *llc_msg, size_t llc_msg_size)
340{
341 /* GPRS Network Service, PDU type: NS_UNITDATA */
342 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
343 unsigned char msg[4096] = {
344 0x01, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
345 0x08, 0x88, /* RAI */ 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
346 /* CELL ID */ 0x00, 0x00, 0x00, 0x80, 0x0e, /* LLC LEN */ 0x00, 0x00,
347 };
348
349 size_t bssgp_msg_size = 23 + llc_msg_size;
350
351 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg));
352
353 gsm48_construct_ra(msg + 10, raid);
354 msg[1] = (uint8_t)(tlli >> 24);
355 msg[2] = (uint8_t)(tlli >> 16);
356 msg[3] = (uint8_t)(tlli >> 8);
357 msg[4] = (uint8_t)(tlli >> 0);
358 msg[16] = cell_id / 256;
359 msg[17] = cell_id % 256;
360 msg[21] = llc_msg_size / 256;
361 msg[22] = llc_msg_size % 256;
362 memcpy(msg + 23, llc_msg, llc_msg_size);
363
364 send_ns_unitdata(nsi, text ? text : "BSSGP UL UNITDATA",
365 src_addr, nsbvci, msg, bssgp_msg_size);
366}
367
368static void send_bssgp_dl_unitdata(
369 struct gprs_ns_inst *nsi, const char *text,
370 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
371 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
372 const uint8_t *llc_msg, size_t llc_msg_size)
373{
374 /* Base Station Subsystem GPRS Protocol: DL_UNITDATA */
375 unsigned char msg[4096] = {
376 0x00, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20,
377 0x16, 0x82, 0x02, 0x58,
378 };
379 unsigned char racap_drx[] = {
380 0x13, 0x99, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96,
381 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62,
382 0x00, 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00,
383 0x60, 0x80, 0x00, 0x0a, 0x82, 0x08, 0x02
384 };
385
386 size_t bssgp_msg_size = 0;
387
388 OSMO_ASSERT(51 + imsi_size + llc_msg_size <= sizeof(msg));
389
390 msg[1] = (uint8_t)(tlli >> 24);
391 msg[2] = (uint8_t)(tlli >> 16);
392 msg[3] = (uint8_t)(tlli >> 8);
393 msg[4] = (uint8_t)(tlli >> 0);
394
395 bssgp_msg_size = 12;
396
397 if (with_racap_drx) {
398 memcpy(msg + bssgp_msg_size, racap_drx, sizeof(racap_drx));
399 bssgp_msg_size += sizeof(racap_drx);
400 }
401
402 if (imsi) {
403 OSMO_ASSERT(imsi_size <= 127);
404 msg[bssgp_msg_size] = BSSGP_IE_IMSI;
405 msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
406 memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
407 bssgp_msg_size += 2 + imsi_size;
408 }
409
410 if ((bssgp_msg_size % 4) != 0) {
411 size_t abytes = (4 - (bssgp_msg_size + 2) % 4) % 4;
412 msg[bssgp_msg_size] = BSSGP_IE_ALIGNMENT;
413 msg[bssgp_msg_size + 1] = 0x80 | abytes;
414 memset(msg + bssgp_msg_size + 2, 0, abytes);
415 bssgp_msg_size += 2 + abytes;
416 }
417
418 msg[bssgp_msg_size] = BSSGP_IE_LLC_PDU;
419 if (llc_msg_size < 128) {
420 msg[bssgp_msg_size + 1] = 0x80 | llc_msg_size;
421 bssgp_msg_size += 2;
422 } else {
423 msg[bssgp_msg_size + 1] = llc_msg_size / 256;
424 msg[bssgp_msg_size + 2] = llc_msg_size % 256;
425 bssgp_msg_size += 3;
426 }
427 memcpy(msg + bssgp_msg_size, llc_msg, llc_msg_size);
428 bssgp_msg_size += llc_msg_size;
429
430
431 send_ns_unitdata(nsi, text ? text : "BSSGP DL UNITDATA",
432 src_addr, nsbvci, msg, bssgp_msg_size);
433}
434
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200435static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
436 uint16_t bvci)
437{
438 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
439 * BSSGP RESET */
Jacob Erlbeckda4b4922014-08-06 12:38:10 +0200440 unsigned char msg[18] = {
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200441 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200442 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
443 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200444 };
445
446 msg[3] = bvci / 256;
447 msg[4] = bvci % 256;
448
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200449 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
450}
451
452static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
453 struct sockaddr_in *src_addr, uint16_t bvci)
454{
455 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
456 * BSSGP RESET_ACK */
457 static unsigned char msg[5] = {
458 0x23, 0x04, 0x82, 0x00,
459 0x00
460 };
461
462 msg[3] = bvci / 256;
463 msg[4] = bvci % 256;
464
465 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200466}
467
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200468static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
469 struct sockaddr_in *src_addr,
470 struct gprs_ra_id *raid)
471{
472 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
473 unsigned char msg[15] = {
474 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
475 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
476 };
477
478 gsm48_construct_ra(msg + 9, raid);
479
480 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
481}
482
483static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
484 struct sockaddr_in *src_addr,
485 struct gprs_ra_id *raid)
486{
487 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
488 unsigned char msg[18] = {
489 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
490 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
491 0x81, 0x01
492 };
493
494 gsm48_construct_ra(msg + 9, raid);
495
496 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
497}
498
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200499static void send_llc_ul_ui(
500 struct gprs_ns_inst *nsi, const char *text,
501 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
502 struct gprs_ra_id *raid, uint16_t cell_id,
503 unsigned sapi, unsigned nu,
504 const uint8_t *msg, size_t msg_size)
505{
506 unsigned char llc_msg[4096] = {
507 0x00, 0xc0, 0x01
508 };
509
510 size_t llc_msg_size = 3 + msg_size + 3;
511 uint8_t e_bit = 0;
512 uint8_t pm_bit = 1;
513 unsigned fcs;
514
515 nu &= 0x01ff;
516
517 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
518
519 llc_msg[0] = (sapi & 0x0f);
520 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
521 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
522
523 memcpy(llc_msg + 3, msg, msg_size);
524
525 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
526 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
527 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
528 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
529
530 send_bssgp_ul_unitdata(nsi, text ? text : "LLC UI",
531 src_addr, nsbvci, tlli, raid, cell_id,
532 llc_msg, llc_msg_size);
533}
534
535static void send_llc_dl_ui(
536 struct gprs_ns_inst *nsi, const char *text,
537 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
538 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
539 unsigned sapi, unsigned nu,
540 const uint8_t *msg, size_t msg_size)
541{
542 /* GPRS Network Service, PDU type: NS_UNITDATA */
543 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
544 unsigned char llc_msg[4096] = {
545 0x00, 0x00, 0x01
546 };
547
548 size_t llc_msg_size = 3 + msg_size + 3;
549 uint8_t e_bit = 0;
550 uint8_t pm_bit = 1;
551 unsigned fcs;
552
553 nu &= 0x01ff;
554
555 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
556
557 llc_msg[0] = 0x40 | (sapi & 0x0f);
558 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
559 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
560
561 memcpy(llc_msg + 3, msg, msg_size);
562
563 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
564 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
565 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
566 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
567
568 send_bssgp_dl_unitdata(nsi, text ? text : "LLC UI",
569 src_addr, nsbvci, tlli,
570 with_racap_drx, imsi, imsi_size,
571 llc_msg, llc_msg_size);
572}
573
574
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200575static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
576 uint16_t nsvci, uint16_t nsei)
577{
578 printf("Setup NS-VC: remote 0x%08x:%d, "
579 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
580 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
581 nsvci, nsvci, nsei, nsei);
582
583 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
584 send_ns_alive(nsi, src_addr);
585 send_ns_unblock(nsi, src_addr);
586 send_ns_alive_ack(nsi, src_addr);
587}
588
589static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
590 uint16_t bvci)
591{
592 printf("Setup BSSGP: remote 0x%08x:%d, "
593 "BVCI 0x%04x(%d)\n\n",
594 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
595 bvci, bvci);
596
597 send_bssgp_reset(nsi, src_addr, bvci);
598}
599
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200600static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
601{
602 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
603 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
604 send_ns_alive_ack(nsi, sgsn_peer);
605 send_ns_unblock_ack(nsi, sgsn_peer);
606 send_ns_alive(nsi, sgsn_peer);
607}
608
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200609static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
610{
611 sgsn_peer->sin_family = AF_INET;
612 sgsn_peer->sin_port = htons(32000);
613 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
614}
615
616static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
617{
618 size_t i;
619
620 for (i = 0; i < size; ++i) {
621 bss_peers[i].sin_family = AF_INET;
622 bss_peers[i].sin_port = htons((i + 1) * 1111);
623 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
624 }
625}
626
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200627int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
628 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
629
630/* override */
631int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
632 struct msgb *msg, uint16_t bvci)
633{
634 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
635 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200636 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200637
638 switch (event) {
639 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +0200640 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200641 default:
642 break;
643 }
644 return 0;
645}
646
647/* override */
648ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
649 const struct sockaddr *dest_addr, socklen_t addrlen)
650{
651 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
652 const struct sockaddr *, socklen_t);
653 static sendto_t real_sendto = NULL;
654 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200655 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200656
657 if (!real_sendto)
658 real_sendto = dlsym(RTLD_NEXT, "sendto");
659
660 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200661 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
662 dest_host, dest_port,
663 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200664 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200665 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
666 dest_host, dest_port,
667 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200668 else
669 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
670
671 return len;
672}
673
674/* override */
675int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
676{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200677 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
678 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200679 uint16_t bvci = msgb_bvci(msg);
680 uint16_t nsei = msgb_nsei(msg);
681
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200682 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200683
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200684 if (!real_gprs_ns_sendmsg)
685 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
686
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200687 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200688 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
689 "msg length %d (%s)\n",
690 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200691 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200692 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
693 "msg length %d (%s)\n",
694 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200695
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200696 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200697}
698
699static void dump_rate_ctr_group(FILE *stream, const char *prefix,
700 struct rate_ctr_group *ctrg)
701{
702 unsigned int i;
703
704 for (i = 0; i < ctrg->desc->num_ctr; i++) {
705 struct rate_ctr *ctr = &ctrg->ctr[i];
706 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
707 fprintf(stream, " %s%s: %llu%s",
708 prefix, ctrg->desc->ctr_desc[i].description,
709 (long long)ctr->current,
710 "\n");
711 };
712}
713
714/* Signal handler for signals from NS layer */
715static int test_signal(unsigned int subsys, unsigned int signal,
716 void *handler_data, void *signal_data)
717{
718 struct ns_signal_data *nssd = signal_data;
719 int rc;
720
721 if (subsys != SS_L_NS)
722 return 0;
723
724 switch (signal) {
725 case S_NS_RESET:
726 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
727 nssd->nsvc->nsvci,
728 gprs_ns_ll_str(nssd->nsvc));
729 break;
730
731 case S_NS_ALIVE_EXP:
732 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
733 nssd->nsvc->nsvci,
734 gprs_ns_ll_str(nssd->nsvc));
735 break;
736
737 case S_NS_BLOCK:
738 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
739 nssd->nsvc->nsvci,
740 gprs_ns_ll_str(nssd->nsvc));
741 break;
742
743 case S_NS_UNBLOCK:
744 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
745 nssd->nsvc->nsvci,
746 gprs_ns_ll_str(nssd->nsvc));
747 break;
748
749 case S_NS_REPLACED:
750 printf("==> got signal NS_REPLACED: 0x%04x/%s",
751 nssd->nsvc->nsvci,
752 gprs_ns_ll_str(nssd->nsvc));
753 printf(" -> 0x%04x/%s\n",
754 nssd->old_nsvc->nsvci,
755 gprs_ns_ll_str(nssd->old_nsvc));
756 break;
757
758 default:
759 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
760 nssd->nsvc->nsvci,
761 gprs_ns_ll_str(nssd->nsvc));
762 break;
763 }
764 printf("\n");
765 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
766 return rc;
767}
768
769static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
770{
771 struct msgb *msg;
772 int ret;
773 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
774 fprintf(stderr, "message too long: %d\n", data_len);
775 return -1;
776 }
777
778 msg = gprs_ns_msgb_alloc();
779 memmove(msg->data, data, data_len);
780 msg->l2h = msg->data;
781 msgb_put(msg, data_len);
782
783 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
784 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
785 osmo_hexdump(data, data_len));
786
787 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
788
789 printf("result (%s) = %d\n\n", text, ret);
790
791 msgb_free(msg);
792
793 return ret;
794}
795
796static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
797{
798 struct gprs_nsvc *nsvc;
799
800 printf("Current NS-VCIs:\n");
801 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
802 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200803 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200804 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200805 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
806 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
807 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200808 );
809 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
810 }
811 printf("\n");
812}
813
814static void test_gbproxy()
815{
816 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
817 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200818 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200819
820 bssgp_nsi = nsi;
821 gbcfg.nsi = bssgp_nsi;
822 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
823
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200824 configure_sgsn_peer(&sgsn_peer);
825 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200826
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200827 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200828 printf("--- Initialise SGSN ---\n\n");
829
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200830 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200831 gprs_dump_nsi(nsi);
832
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200833 printf("--- Initialise BSS 1 ---\n\n");
834
835 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
836 setup_bssgp(nsi, &bss_peer[0], 0x1002);
837 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200838 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200839
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200840 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
841
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200842 printf("--- Initialise BSS 2 ---\n\n");
843
844 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
845 setup_bssgp(nsi, &bss_peer[1], 0x2002);
846 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200847 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200848
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200849 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
850
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200851 printf("--- Move BSS 1 to new port ---\n\n");
852
853 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
854 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200855 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200856
857 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
858
859 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
860 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200861 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200862
863 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
864
865 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
866 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200867 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200868
869 printf("--- Move BSS 2 to new port ---\n\n");
870
871 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
872 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200873 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200874
875 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
876
877 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
878 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200879 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200880
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200881 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
882
883 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
884 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200885 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200886
887 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
888
889 setup_bssgp(nsi, &bss_peer[0], 0x1012);
890 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200891 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200892
893 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
894
895 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
896
897 setup_bssgp(nsi, &bss_peer[0], 0x1002);
898 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200899 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200900
901 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
902
903 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
904
905 setup_bssgp(nsi, &bss_peer[0], 0x1002);
906 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200907 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200908
909 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
910
911 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
912
913 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
914
915 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
916
917 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
918
919 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
920
921 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
922
923 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
924
925 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
926
927 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
928
929 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
930
931 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
932
933 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
934
935 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
936
937 setup_bssgp(nsi, &bss_peer[2], 0x1002);
938 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200939 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200940
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200941 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200942
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200943 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
944
945 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
946
947 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
948
949 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
950
951 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
952
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200953 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
954
955 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
956
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200957 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200958
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +0200959 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200960 gprs_ns_destroy(nsi);
961 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200962}
963
964static void test_gbproxy_ident_changes()
965{
966 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
967 struct sockaddr_in bss_peer[1] = {{0},};
968 struct sockaddr_in sgsn_peer= {0};
969 uint16_t nsei[2] = {0x1000, 0x2000};
970 uint16_t nsvci[2] = {0x1001, 0x2001};
971 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
972
973 bssgp_nsi = nsi;
974 gbcfg.nsi = bssgp_nsi;
975 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
976
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200977 configure_sgsn_peer(&sgsn_peer);
978 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200979
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200980 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200981 printf("--- Initialise SGSN ---\n\n");
982
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200983 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200984 gprs_dump_nsi(nsi);
985
986 printf("--- Initialise BSS 1 ---\n\n");
987
988 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
989 gprs_dump_nsi(nsi);
990
991 printf("--- Setup BVCI 1 ---\n\n");
992
993 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
994 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200995 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200996
997 printf("--- Setup BVCI 2 ---\n\n");
998
999 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
1000 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001001 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001002
1003 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1004
1005 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1006 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1007
1008 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
1009
1010 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
1011 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
1012
1013 printf("--- Change NSEI ---\n\n");
1014
1015 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
1016 gprs_dump_nsi(nsi);
1017
1018 printf("--- Setup BVCI 1 ---\n\n");
1019
1020 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1021 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001022 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001023
1024 printf("--- Setup BVCI 3 ---\n\n");
1025
1026 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
1027 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001028 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001029
1030 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1031
1032 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1033 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1034
1035 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1036 " (should fail) ---\n\n");
1037
1038 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001039 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001040 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001041 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001042
1043 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1044
1045 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1046 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1047
1048 printf("--- Change NSVCI ---\n\n");
1049
1050 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
1051 gprs_dump_nsi(nsi);
1052
1053 printf("--- Setup BVCI 1 ---\n\n");
1054
1055 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1056 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001057 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001058
1059 printf("--- Setup BVCI 4 ---\n\n");
1060
1061 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
1062 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001063 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001064
1065 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1066
1067 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1068 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1069
1070 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1071 " (should fail) ---\n\n");
1072
1073 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001074 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001075 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001076 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001077
1078 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1079
1080 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1081 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1082
1083 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
1084
1085 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
1086 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
1087
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001088 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001089 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001090
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001091 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001092 gprs_ns_destroy(nsi);
1093 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001094}
1095
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001096static void test_gbproxy_ra_patching()
1097{
1098 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1099 struct sockaddr_in bss_peer[1] = {{0},};
1100 struct sockaddr_in sgsn_peer= {0};
1101 struct gprs_ra_id rai_bss =
1102 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1103 struct gprs_ra_id rai_sgsn =
1104 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
1105 struct gprs_ra_id rai_unknown =
1106 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001107 uint16_t cell_id = 0x7530;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001108 const char *err_msg = NULL;
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001109 const uint32_t ptmsi = 0xefe2b700;
1110 const uint32_t local_tlli = 0xefe2b700;
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001111 const uint32_t foreign_tlli = 0xbbc54679;
1112 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001113 struct gbproxy_tlli_info *tlli_info;
1114 struct gbproxy_peer *peer;
1115
1116 OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001117
1118 bssgp_nsi = nsi;
1119 gbcfg.nsi = bssgp_nsi;
1120 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +02001121 gbcfg.core_mcc = 123;
1122 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +02001123 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +02001124 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001125 gbcfg.patch_ptmsi = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001126
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001127 configure_sgsn_peer(&sgsn_peer);
1128 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001129
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001130 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Holger Hans Peter Freyther3fa26442014-08-04 16:27:11 +02001131 if (gbprox_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001132 fprintf(stderr, "Failed to compile RE '%s': %s\n",
1133 gbcfg.match_re, err_msg);
1134 exit(1);
1135 }
1136
1137
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001138 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001139 printf("--- Initialise SGSN ---\n\n");
1140
1141 connect_sgsn(nsi, &sgsn_peer);
1142 gprs_dump_nsi(nsi);
1143
1144 printf("--- Initialise BSS 1 ---\n\n");
1145
1146 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1147 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1148 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001149 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001150
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001151 peer = gbprox_peer_by_nsei(&gbcfg, 0x1000);
1152 OSMO_ASSERT(peer != NULL);
1153
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001154 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1155
1156 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
1157 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
1158
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001159 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001160 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001161
1162 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1163
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001164 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1165 foreign_tlli, &rai_bss, cell_id,
1166 GPRS_SAPI_GMM, 0,
1167 dtap_attach_req, sizeof(dtap_attach_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001168
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001169 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1170 foreign_tlli, 0, NULL, 0,
1171 GPRS_SAPI_GMM, 0,
1172 dtap_identity_req, sizeof(dtap_identity_req));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001173
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001174 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1175 foreign_tlli, &rai_bss, cell_id,
1176 GPRS_SAPI_GMM, 3,
1177 dtap_identity_resp, sizeof(dtap_identity_resp));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001178
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001179 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1180 foreign_tlli, 1, imsi, sizeof(imsi),
1181 GPRS_SAPI_GMM, 1,
1182 dtap_attach_acc, sizeof(dtap_attach_acc));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001183
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001184 tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001185 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001186 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1187 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1188 OSMO_ASSERT(!tlli_info->tlli.bss_validated);
1189 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1190 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1191 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1192 OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
1193 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001194
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001195 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1196 local_tlli, &rai_bss, cell_id,
1197 GPRS_SAPI_GMM, 4,
1198 dtap_attach_complete, sizeof(dtap_attach_complete));
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001199
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001200 tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001201 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001202 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1203 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1204 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1205 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1206 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1207 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1208 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1209 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001210
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001211 /* Replace APN (1) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001212 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1213 local_tlli, &rai_bss, cell_id,
1214 GPRS_SAPI_GMM, 3,
1215 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001216
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001217 tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001218 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001219 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1220 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1221 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1222 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1223 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1224 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1225 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1226 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001227
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001228 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1229 local_tlli, 1, imsi, sizeof(imsi),
1230 GPRS_SAPI_GMM, 2,
1231 dtap_gmm_information, sizeof(dtap_gmm_information));
Jacob Erlbeck11669742014-06-06 18:47:36 +02001232
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001233 tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001234 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001235 OSMO_ASSERT(tlli_info->tlli.assigned == 0);
1236 OSMO_ASSERT(tlli_info->tlli.current == local_tlli);
1237 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
1238 OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001239
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001240 /* Replace APN (2) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001241 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1242 local_tlli, &rai_bss, cell_id,
1243 GPRS_SAPI_GMM, 3,
1244 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001245
Jacob Erlbeck73685282014-05-23 20:48:07 +02001246 gbcfg.core_apn[0] = 0;
1247 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001248
1249 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001250 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1251 local_tlli, &rai_bss, cell_id,
1252 GPRS_SAPI_GMM, 3,
1253 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001254
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001255 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001256
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001257 /* Detach */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001258 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1259 local_tlli, &rai_bss, cell_id,
1260 GPRS_SAPI_GMM, 6,
1261 dtap_detach_req, sizeof(dtap_detach_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001262
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001263 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1264 local_tlli, 1, imsi, sizeof(imsi),
1265 GPRS_SAPI_GMM, 5,
1266 dtap_detach_acc, sizeof(dtap_detach_acc));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001267
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001268 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001269
1270 printf("--- RA update ---\n\n");
1271
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001272 send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1273 foreign_tlli, &rai_bss, 0x7080,
1274 GPRS_SAPI_GMM, 5,
1275 dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001276
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001277 send_llc_dl_ui(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1278 foreign_tlli, 1, imsi, sizeof(imsi),
1279 GPRS_SAPI_GMM, 6,
1280 dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001281
1282 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001283 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1284 local_tlli, &rai_bss, cell_id,
1285 GPRS_SAPI_GMM, 3,
1286 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001287
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001288 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001289
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +02001290 /* Detach (power off -> no Detach Accept) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001291 send_llc_ul_ui(nsi, "DETACH REQ (PWR OFF)", &bss_peer[0], 0x1002,
1292 local_tlli, &rai_bss, cell_id,
1293 GPRS_SAPI_GMM, 6,
1294 dtap_detach_po_req, sizeof(dtap_detach_po_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001295
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001296 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001297 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001298
1299 printf("--- Bad cases ---\n\n");
1300
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001301 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001302 send_llc_ul_ui(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1303 local_tlli, &rai_bss, cell_id,
1304 GPRS_SAPI_GMM, 3,
1305 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001306
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001307 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001308 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1309
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001310 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001311 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001312
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001313 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001314 gprs_ns_destroy(nsi);
1315 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001316}
1317
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001318/* TODO: Move tlv testing to libosmocore */
1319int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1320int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1321 uint8_t **value);
1322int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1323 size_t *value_len);
1324int lv_shift(uint8_t **data, size_t *data_len,
1325 uint8_t **value, size_t *value_len);
1326
1327static void check_tlv_match(uint8_t **data, size_t *data_len,
1328 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1329{
1330 uint8_t *value;
1331 size_t value_len;
1332 int rc;
1333
1334 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1335 OSMO_ASSERT(rc == 0);
1336
1337 rc = tlv_match(data, data_len, tag, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001338 OSMO_ASSERT(rc == (int)value_len + 2);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001339 OSMO_ASSERT(value_len == exp_len);
1340 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1341}
1342
1343static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1344 uint8_t tag, size_t len, const uint8_t *exp_val)
1345{
1346 uint8_t *value;
1347 int rc;
1348
1349 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1350 OSMO_ASSERT(rc == 0);
1351
1352 rc = tv_fixed_match(data, data_len, tag, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001353 OSMO_ASSERT(rc == (int)len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001354 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1355}
1356
1357static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1358 size_t len, const uint8_t *exp_val)
1359{
1360 uint8_t *value;
1361 int rc;
1362
1363 rc = v_fixed_shift(data, data_len, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001364 OSMO_ASSERT(rc == (int)len);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001365 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1366}
1367
1368static void check_lv_shift(uint8_t **data, size_t *data_len,
1369 size_t exp_len, const uint8_t *exp_val)
1370{
1371 uint8_t *value;
1372 size_t value_len;
1373 int rc;
1374
1375 rc = lv_shift(data, data_len, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001376 OSMO_ASSERT(rc == (int)value_len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001377 OSMO_ASSERT(value_len == exp_len);
1378 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1379}
1380
1381static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1382 const uint8_t *test_data)
1383{
1384 uint8_t buf[300] = {0};
1385
1386 uint8_t *unchanged_ptr = buf - 1;
1387 size_t unchanged_len = 0xdead;
1388 size_t tmp_data_len = data_len;
1389 uint8_t *value = unchanged_ptr;
1390 size_t value_len = unchanged_len;
1391 uint8_t *data = buf;
1392
1393 OSMO_ASSERT(data_len <= sizeof(buf));
1394
1395 tlv_put(data, tag, len, test_data);
1396 if (data_len < len + 2) {
1397 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1398 tag, &value, &value_len));
1399 OSMO_ASSERT(tmp_data_len == 0);
1400 OSMO_ASSERT(data == buf + data_len);
1401 OSMO_ASSERT(value == unchanged_ptr);
1402 OSMO_ASSERT(value_len == unchanged_len);
1403 } else {
1404 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1405 tag, &value, &value_len));
1406 OSMO_ASSERT(value != unchanged_ptr);
1407 OSMO_ASSERT(value_len != unchanged_len);
1408 }
1409}
1410
1411static void check_tv_fixed_match_data_len(size_t data_len,
1412 uint8_t tag, size_t len,
1413 const uint8_t *test_data)
1414{
1415 uint8_t buf[300] = {0};
1416
1417 uint8_t *unchanged_ptr = buf - 1;
1418 size_t tmp_data_len = data_len;
1419 uint8_t *value = unchanged_ptr;
1420 uint8_t *data = buf;
1421
1422 OSMO_ASSERT(data_len <= sizeof(buf));
1423
1424 tv_fixed_put(data, tag, len, test_data);
1425
1426 if (data_len < len + 1) {
1427 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1428 tag, len, &value));
1429 OSMO_ASSERT(tmp_data_len == 0);
1430 OSMO_ASSERT(data == buf + data_len);
1431 OSMO_ASSERT(value == unchanged_ptr);
1432 } else {
1433 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1434 tag, len, &value));
1435 OSMO_ASSERT(value != unchanged_ptr);
1436 }
1437}
1438
1439static void check_v_fixed_shift_data_len(size_t data_len,
1440 size_t len, const uint8_t *test_data)
1441{
1442 uint8_t buf[300] = {0};
1443
1444 uint8_t *unchanged_ptr = buf - 1;
1445 size_t tmp_data_len = data_len;
1446 uint8_t *value = unchanged_ptr;
1447 uint8_t *data = buf;
1448
1449 OSMO_ASSERT(data_len <= sizeof(buf));
1450
1451 memcpy(data, test_data, len);
1452
1453 if (data_len < len) {
1454 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1455 len, &value));
1456 OSMO_ASSERT(tmp_data_len == 0);
1457 OSMO_ASSERT(data == buf + data_len);
1458 OSMO_ASSERT(value == unchanged_ptr);
1459 } else {
1460 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1461 len, &value));
1462 OSMO_ASSERT(value != unchanged_ptr);
1463 }
1464}
1465
1466static void check_lv_shift_data_len(size_t data_len,
1467 size_t len, const uint8_t *test_data)
1468{
1469 uint8_t buf[300] = {0};
1470
1471 uint8_t *unchanged_ptr = buf - 1;
1472 size_t unchanged_len = 0xdead;
1473 size_t tmp_data_len = data_len;
1474 uint8_t *value = unchanged_ptr;
1475 size_t value_len = unchanged_len;
1476 uint8_t *data = buf;
1477
1478 lv_put(data, len, test_data);
1479 if (data_len < len + 1) {
1480 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1481 &value, &value_len));
1482 OSMO_ASSERT(tmp_data_len == 0);
1483 OSMO_ASSERT(data == buf + data_len);
1484 OSMO_ASSERT(value == unchanged_ptr);
1485 OSMO_ASSERT(value_len == unchanged_len);
1486 } else {
1487 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1488 &value, &value_len));
1489 OSMO_ASSERT(value != unchanged_ptr);
1490 OSMO_ASSERT(value_len != unchanged_len);
1491 }
1492}
1493
1494static void test_tlv_shift_functions()
1495{
1496 uint8_t test_data[1024];
1497 uint8_t buf[1024];
1498 uint8_t *data_end;
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001499 unsigned i, len;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001500 uint8_t *data;
1501 size_t data_len;
1502 const uint8_t tag = 0x1a;
1503
1504 printf("Test shift functions\n");
1505
1506 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1507 test_data[i] = (uint8_t)i;
1508
1509 for (len = 0; len < 256; len++) {
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001510 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001511
1512 memset(buf, 0xee, sizeof(buf));
1513 data_end = data = buf;
1514
1515 for (i = 0; i < iterations; i++) {
1516 data_end = tlv_put(data_end, tag, len, test_data);
1517 data_end = tv_fixed_put(data_end, tag, len, test_data);
1518 /* v_fixed_put */
1519 memcpy(data_end, test_data, len);
1520 data_end += len;
1521 data_end = lv_put(data_end, len, test_data);
1522 }
1523
1524 data_len = data_end - data;
1525 OSMO_ASSERT(data_len <= sizeof(buf));
1526
1527 for (i = 0; i < iterations; i++) {
1528 check_tlv_match(&data, &data_len, tag, len, test_data);
1529 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1530 check_v_fixed_shift(&data, &data_len, len, test_data);
1531 check_lv_shift(&data, &data_len, len, test_data);
1532 }
1533
1534 OSMO_ASSERT(data == data_end);
1535
1536 /* Test at end of data */
1537
1538 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1539 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1540 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1541 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1542
1543 /* Test invalid data_len */
1544 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1545 check_tlv_match_data_len(data_len, tag, len, test_data);
1546 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1547 check_v_fixed_shift_data_len(data_len, len, test_data);
1548 check_lv_shift_data_len(data_len, len, test_data);
1549 }
1550 }
1551}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001552
1553static void test_gbproxy_tlli_expire(void)
1554{
1555 struct gbproxy_config cfg = {0};
1556 struct gbproxy_peer *peer;
1557 const char *err_msg = NULL;
1558 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1559 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001560 const uint8_t imsi3[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0x76, 0xf8 };
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001561 const uint32_t tlli1 = 1234 | 0xc0000000;
1562 const uint32_t tlli2 = 5678 | 0xc0000000;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001563 const uint32_t tlli3 = 3456 | 0xc0000000;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001564 const char *filter_re = ".*";
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001565 time_t now = 1407479214;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001566
1567 printf("Test TLLI info expiry\n\n");
1568
1569 gbproxy_init_config(&cfg);
1570
1571 if (gbprox_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
1572 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1573 err_msg);
1574 OSMO_ASSERT(err_msg == NULL);
1575 }
1576
1577 {
1578 struct gbproxy_tlli_info *tlli_info;
1579
1580 printf("Test TLLI replacement:\n");
1581
1582 cfg.tlli_max_len = 0;
1583 cfg.tlli_max_age = 0;
1584 peer = gbproxy_peer_alloc(&cfg, 20);
1585 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1586
1587 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001588 tlli_info = gbprox_register_tlli(peer, tlli1,
1589 imsi1, ARRAY_SIZE(imsi1), now);
1590 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001591 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001592 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1593
1594 /* replace the old entry */
1595 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001596 tlli_info = gbprox_register_tlli(peer, tlli2,
1597 imsi1, ARRAY_SIZE(imsi1), now);
1598 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001599 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001600 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1601
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001602 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001603
1604 /* verify that 5678 has survived */
1605 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1606 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001607 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001608 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1609 OSMO_ASSERT(!tlli_info);
1610
1611 printf("\n");
1612
1613 gbproxy_peer_free(peer);
1614 }
1615
1616 {
1617 struct gbproxy_tlli_info *tlli_info;
1618
1619 printf("Test IMSI replacement:\n");
1620
1621 cfg.tlli_max_len = 0;
1622 cfg.tlli_max_age = 0;
1623 peer = gbproxy_peer_alloc(&cfg, 20);
1624 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1625
1626 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001627 tlli_info = gbprox_register_tlli(peer, tlli1,
1628 imsi1, ARRAY_SIZE(imsi1), now);
1629 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001630 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001631 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1632
1633 /* try to replace the old entry */
1634 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001635 tlli_info = gbprox_register_tlli(peer, tlli1,
1636 imsi2, ARRAY_SIZE(imsi2), now);
1637 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001638 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001639 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1640
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001641 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001642
1643 /* verify that 5678 has survived */
1644 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1645 OSMO_ASSERT(!tlli_info);
1646 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1647 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001648 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001649
1650 printf("\n");
1651
1652 gbproxy_peer_free(peer);
1653 }
1654
1655 {
1656 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001657 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001658
1659 printf("Test TLLI expiry, max_len == 1:\n");
1660
1661 cfg.tlli_max_len = 1;
1662 cfg.tlli_max_age = 0;
1663 peer = gbproxy_peer_alloc(&cfg, 20);
1664 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1665
1666 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001667 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001668 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1669
1670 /* replace the old entry */
1671 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001672 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001673 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1674
1675 num_removed = gbprox_remove_stale_tllis(peer, time(NULL) + 2);
1676 OSMO_ASSERT(num_removed == 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001677 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1678
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001679 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001680
1681 /* verify that 5678 has survived */
1682 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1683 OSMO_ASSERT(!tlli_info);
1684 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1685 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001686 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001687
1688 printf("\n");
1689
1690 gbproxy_peer_free(peer);
1691 }
1692
1693 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001694 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001695 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001696
1697 printf("Test TLLI expiry, max_age == 1:\n");
1698
1699 cfg.tlli_max_len = 0;
1700 cfg.tlli_max_age = 1;
1701 peer = gbproxy_peer_alloc(&cfg, 20);
1702 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1703
1704 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001705 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001706 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1707
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001708 printf(" Add TLLI 2, IMSI 2 (should not expire after timeout)\n");
1709 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
1710 now + 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001711 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1712
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001713 num_removed = gbprox_remove_stale_tllis(peer, now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001714 OSMO_ASSERT(num_removed == 1);
1715 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1716
1717 dump_peers(stdout, 2, now + 2, &cfg);
1718
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001719 /* verify that 5678 has survived */
1720 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1721 OSMO_ASSERT(!tlli_info);
1722 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1723 OSMO_ASSERT(tlli_info);
1724 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
1725
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001726 printf("\n");
1727
1728 gbproxy_peer_free(peer);
1729 }
1730
1731 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001732 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001733 int num_removed;
1734
1735 printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
1736
1737 cfg.tlli_max_len = 0;
1738 cfg.tlli_max_age = 1;
1739 peer = gbproxy_peer_alloc(&cfg, 20);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001740 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1741
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001742 printf(" Add TLLI 1, IMSI 1 (should expire)\n");
1743 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
1744 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1745
1746 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
1747 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
1748 now + 1);
1749 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1750
1751 printf(" Add TLLI 3, IMSI 3 (should not expire after timeout)\n");
1752 gbprox_register_tlli(peer, tlli3, imsi3, ARRAY_SIZE(imsi3),
1753 now + 2);
1754 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 3);
1755
1756 dump_peers(stdout, 2, now + 2, &cfg);
1757
1758 printf(" Remove stale TLLIs\n");
1759 num_removed = gbprox_remove_stale_tllis(peer, now + 3);
1760 OSMO_ASSERT(num_removed == 2);
1761 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1762
1763 dump_peers(stdout, 2, now + 2, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001764
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001765 /* verify that tlli3 has survived */
1766 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1767 OSMO_ASSERT(!tlli_info);
1768 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1769 OSMO_ASSERT(!tlli_info);
1770 tlli_info = gbprox_find_tlli_by_mi(peer, imsi3, ARRAY_SIZE(imsi3));
1771 OSMO_ASSERT(tlli_info);
1772 OSMO_ASSERT(tlli_info->tlli.current == tlli3);
1773
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001774 printf("\n");
1775
1776 gbproxy_peer_free(peer);
1777 }
1778}
1779
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001780static void test_gbproxy_imsi_matching(void)
1781{
1782 struct gbproxy_config cfg = {0};
1783 struct gbproxy_peer *peer;
1784 const char *err_msg = NULL;
1785 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
1786 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1787 const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
1788 const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
1789 const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
1790 const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
1791 const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1792 const char *filter_re1 = ".*";
1793 const char *filter_re2 = "^1234";
1794 const char *filter_re3 = "^4321";
1795 const char *filter_re4_bad = "^12[";
1796
1797 printf("=== Test IMSI/TMSI matching ===\n\n");
1798
1799 gbproxy_init_config(&cfg);
1800 OSMO_ASSERT(cfg.check_imsi == 0);
1801
1802 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
1803 OSMO_ASSERT(cfg.check_imsi == 1);
1804
1805 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1806 OSMO_ASSERT(cfg.check_imsi == 1);
1807
1808 err_msg = NULL;
1809 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
1810 OSMO_ASSERT(err_msg != NULL);
1811 OSMO_ASSERT(cfg.check_imsi == 0);
1812
1813 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1814 OSMO_ASSERT(cfg.check_imsi == 1);
1815
1816 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, NULL, &err_msg) == 0);
1817 OSMO_ASSERT(cfg.check_imsi == 0);
1818
Jacob Erlbeck29805da2014-08-14 08:57:04 +02001819 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1820 OSMO_ASSERT(cfg.check_imsi == 1);
1821
1822 gbprox_clear_patch_filter(&cfg);
1823 OSMO_ASSERT(cfg.check_imsi == 0);
1824
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001825 peer = gbproxy_peer_alloc(&cfg, 20);
1826
1827 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1828 OSMO_ASSERT(cfg.check_imsi == 1);
1829
1830 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
1831 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
1832 /* imsi3_bad contains 0xE and 0xF digits, but the conversion function
1833 * doesn't complain, so gbprox_check_imsi() doesn't return -1 in this
1834 * case. */
1835 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1836 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1837 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1838 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1839 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1840
1841 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
1842 OSMO_ASSERT(cfg.check_imsi == 1);
1843
1844 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
1845 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
1846 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1847 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1848 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1849 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1850 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1851
1852 /* TODO: Check correct length but wrong type with is_mi_tmsi */
1853
1854 gbproxy_peer_free(peer);
1855}
1856
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001857static struct log_info_cat gprs_categories[] = {
1858 [DGPRS] = {
1859 .name = "DGPRS",
1860 .description = "GPRS Packet Service",
1861 .enabled = 1, .loglevel = LOGL_DEBUG,
1862 },
1863 [DNS] = {
1864 .name = "DNS",
1865 .description = "GPRS Network Service (NS)",
1866 .enabled = 1, .loglevel = LOGL_INFO,
1867 },
1868 [DBSSGP] = {
1869 .name = "DBSSGP",
1870 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1871 .enabled = 1, .loglevel = LOGL_DEBUG,
1872 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001873};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001874
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001875static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001876 .cat = gprs_categories,
1877 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001878};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001879
1880int main(int argc, char **argv)
1881{
1882 osmo_init_logging(&info);
1883 log_set_use_color(osmo_stderr_target, 0);
1884 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001885 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001886
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001887 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001888 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1889 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001890
1891 rate_ctr_init(NULL);
1892
1893 setlinebuf(stdout);
1894
1895 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02001896 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001897 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001898 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001899 test_gbproxy_ident_changes();
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001900 test_gbproxy_imsi_matching();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001901 test_gbproxy_ra_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001902 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001903 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001904
1905 exit(EXIT_SUCCESS);
1906}