blob: 10f3a26501742df80a5ffb4eb4d5f90930a1b230 [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 Erlbeck51a869c2013-10-15 12:00:26 +020028#include <osmocom/gprs/gprs_msgb.h>
29#include <osmocom/gprs/gprs_ns.h>
30#include <osmocom/gprs/gprs_bssgp.h>
31
32#include <openbsc/gb_proxy.h>
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020033#include <openbsc/gprs_utils.h>
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020034#include <openbsc/debug.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020035
36#define REMOTE_BSS_ADDR 0x01020304
37#define REMOTE_SGSN_ADDR 0x05060708
38
Jacob Erlbeck2082afa2013-10-18 13:04:47 +020039#define SGSN_NSEI 0x0100
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020040
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020041struct gbproxy_config gbcfg = {0};
42
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020043static int dump_global(FILE *stream, int indent)
44{
45 unsigned int i;
46 const struct rate_ctr_group_desc *desc;
47 int rc;
48
49 rc = fprintf(stream, "%*sGbproxy global:\n", indent, "");
50 if (rc < 0)
51 return rc;
52
53 desc = gbcfg.ctrg->desc;
54
55 for (i = 0; i < desc->num_ctr; i++) {
56 struct rate_ctr *ctr = &gbcfg.ctrg->ctr[i];
57 if (ctr->current) {
58 rc = fprintf(stream, "%*s %s: %llu\n",
59 indent, "",
60 desc->ctr_desc[i].description,
61 (long long)ctr->current);
62
63 if (rc < 0)
64 return rc;
65 }
66 }
67
68 return 0;
69}
70
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +020071static int dump_peers(FILE *stream, int indent, struct gbproxy_config *cfg)
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020072{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020073 struct gbproxy_peer *peer;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020074 struct gprs_ra_id raid;
75 unsigned int i;
76 const struct rate_ctr_group_desc *desc;
77 int rc;
78 time_t now = time(NULL);
79
80 rc = fprintf(stream, "%*sPeers:\n", indent, "");
81 if (rc < 0)
82 return rc;
83
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +020084 llist_for_each_entry(peer, &cfg->bts_peers, list) {
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020085 struct gbproxy_tlli_info *tlli_info;
86 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020087 gsm48_parse_ra(&raid, peer->ra);
88
89 rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, "
90 "RAI %u-%u-%u-%u\n",
91 indent, "",
92 peer->nsei, peer->bvci,
93 peer->blocked ? "" : "not ",
94 raid.mcc, raid.mnc, raid.lac, raid.rac);
95
96 if (rc < 0)
97 return rc;
98
99 desc = peer->ctrg->desc;
100
101 for (i = 0; i < desc->num_ctr; i++) {
102 struct rate_ctr *ctr = &peer->ctrg->ctr[i];
103 if (ctr->current) {
104 rc = fprintf(stream, "%*s %s: %llu\n",
105 indent, "",
106 desc->ctr_desc[i].description,
107 (long long)ctr->current);
108
109 if (rc < 0)
110 return rc;
111 }
112 }
113
114 fprintf(stream, "%*s TLLI-Cache: %d\n",
115 indent, "", state->enabled_tllis_count);
116 llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
117 char mi_buf[200];
118 time_t age = now - tlli_info->timestamp;
119 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
120 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
121 tlli_info->mi_data,
122 tlli_info->mi_data_len);
123 rc = fprintf(stream,
124 "%*s TLLI %08x, IMSI %s, AGE %d\n",
125 indent, "",
126 tlli_info->tlli, mi_buf, (int)age);
127 if (rc < 0)
128 return rc;
129 }
130 }
131
132 return 0;
133}
134
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200135/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Request */
136static const unsigned char bssgp_attach_req[75] = {
137 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
138 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
139 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x34, 0x01,
140 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21,
141 0x08, 0x02, 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79,
142 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19, 0x18,
143 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
144 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80,
145 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
146 0x16, 0x6d, 0x01
147};
148
149/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */
150static const unsigned char bssgp_attach_acc[88] = {
151 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
152 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
153 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
154 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
155 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
156 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
157 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
158 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01,
159 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60,
160 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05,
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +0200161 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x42, 0x67, 0x9a
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200162};
163
Jacob Erlbeck11669742014-06-06 18:47:36 +0200164/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - GMM Information */
165static const unsigned char bssgp_gmm_information[66] = {
166 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
167 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
168 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
169 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
170 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
171 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
172 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
173 0x0e, 0x88, 0x41, 0xc0, 0x09, 0x08, 0x21, 0x04,
174 0xba, 0x3d
175};
176
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200177/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */
178static const unsigned char bssgp_ra_upd_req[85] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200179 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200180 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
181 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01,
182 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33,
183 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33,
184 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48,
185 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8,
186 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02,
187 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27,
188 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02,
189 0x20, 0x00, 0x96, 0x3e, 0x97
190};
191
192/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */
193static const unsigned char bssgp_ra_upd_acc[91] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200194 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200195 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13,
196 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02,
197 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48,
198 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8,
199 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d,
200 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
201 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0,
202 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
203 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
204 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16,
205 0xc3, 0xbf, 0xcc
206};
207
208/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */
209static const unsigned char bssgp_act_pdp_ctx_req[76] = {
210 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
211 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
212 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01,
213 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
214 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
216 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
217 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
218 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
219 0x00, 0x5a, 0xff, 0x02
220};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200221
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200222/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Request */
223static const unsigned char bssgp_detach_req[44] = {
224 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
225 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
226 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x15, 0x01,
227 0xc0, 0x19, 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4,
228 0xef, 0xe2, 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97,
229 0xcb, 0x7e, 0xe1, 0x41
230};
231
232/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Accept */
233static const unsigned char bssgp_detach_acc[67] = {
234 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
235 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
236 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
237 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
238 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
239 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
240 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
241 0x0e, 0x89, 0x41, 0xc0, 0x15, 0x08, 0x06, 0x00,
242 0xf7, 0x35, 0xf0
243};
244
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200245static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
246 struct sockaddr_in *peer, const unsigned char* data,
247 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200248
249static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
250 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
251{
252 /* GPRS Network Service, PDU type: NS_RESET,
253 */
254 unsigned char msg[12] = {
255 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
256 0x04, 0x82, 0x11, 0x22
257 };
258
259 msg[3] = cause;
260 msg[6] = nsvci / 256;
261 msg[7] = nsvci % 256;
262 msg[10] = nsei / 256;
263 msg[11] = nsei % 256;
264
265 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
266}
267
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200268static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
269 uint16_t nsvci, uint16_t nsei)
270{
271 /* GPRS Network Service, PDU type: NS_RESET_ACK,
272 */
273 unsigned char msg[9] = {
274 0x03, 0x01, 0x82, 0x11, 0x22,
275 0x04, 0x82, 0x11, 0x22
276 };
277
278 msg[3] = nsvci / 256;
279 msg[4] = nsvci % 256;
280 msg[7] = nsei / 256;
281 msg[8] = nsei % 256;
282
283 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
284}
285
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200286static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
287{
288 /* GPRS Network Service, PDU type: NS_ALIVE */
289 unsigned char msg[1] = {
290 0x0a
291 };
292
293 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
294}
295
296static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
297{
298 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
299 unsigned char msg[1] = {
300 0x0b
301 };
302
303 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
304}
305
306static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
307{
308 /* GPRS Network Service, PDU type: NS_UNBLOCK */
309 unsigned char msg[1] = {
310 0x06
311 };
312
313 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
314}
315
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200316static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
317{
318 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
319 unsigned char msg[1] = {
320 0x07
321 };
322
323 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
324}
325
326static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
327 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200328 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
329{
330 /* GPRS Network Service, PDU type: NS_UNITDATA */
331 unsigned char msg[4096] = {
332 0x00, 0x00, 0x00, 0x00
333 };
334
335 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
336
337 msg[2] = nsbvci / 256;
338 msg[3] = nsbvci % 256;
339 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
340
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200341 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200342}
343
344static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
345 uint16_t bvci)
346{
347 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
348 * BSSGP RESET */
349 unsigned char msg[22] = {
350 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200351 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
352 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200353 };
354
355 msg[3] = bvci / 256;
356 msg[4] = bvci % 256;
357
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200358 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
359}
360
361static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
362 struct sockaddr_in *src_addr, uint16_t bvci)
363{
364 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
365 * BSSGP RESET_ACK */
366 static unsigned char msg[5] = {
367 0x23, 0x04, 0x82, 0x00,
368 0x00
369 };
370
371 msg[3] = bvci / 256;
372 msg[4] = bvci % 256;
373
374 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200375}
376
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200377static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
378 struct sockaddr_in *src_addr,
379 struct gprs_ra_id *raid)
380{
381 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
382 unsigned char msg[15] = {
383 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
384 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
385 };
386
387 gsm48_construct_ra(msg + 9, raid);
388
389 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
390}
391
392static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
393 struct sockaddr_in *src_addr,
394 struct gprs_ra_id *raid)
395{
396 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
397 unsigned char msg[18] = {
398 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
399 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
400 0x81, 0x01
401 };
402
403 gsm48_construct_ra(msg + 9, raid);
404
405 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
406}
407
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200408static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
409 uint16_t nsvci, uint16_t nsei)
410{
411 printf("Setup NS-VC: remote 0x%08x:%d, "
412 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
413 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
414 nsvci, nsvci, nsei, nsei);
415
416 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
417 send_ns_alive(nsi, src_addr);
418 send_ns_unblock(nsi, src_addr);
419 send_ns_alive_ack(nsi, src_addr);
420}
421
422static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
423 uint16_t bvci)
424{
425 printf("Setup BSSGP: remote 0x%08x:%d, "
426 "BVCI 0x%04x(%d)\n\n",
427 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
428 bvci, bvci);
429
430 send_bssgp_reset(nsi, src_addr, bvci);
431}
432
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200433static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
434{
435 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
436 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
437 send_ns_alive_ack(nsi, sgsn_peer);
438 send_ns_unblock_ack(nsi, sgsn_peer);
439 send_ns_alive(nsi, sgsn_peer);
440}
441
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200442static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
443{
444 sgsn_peer->sin_family = AF_INET;
445 sgsn_peer->sin_port = htons(32000);
446 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
447}
448
449static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
450{
451 size_t i;
452
453 for (i = 0; i < size; ++i) {
454 bss_peers[i].sin_family = AF_INET;
455 bss_peers[i].sin_port = htons((i + 1) * 1111);
456 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
457 }
458}
459
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200460int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
461 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
462
463/* override */
464int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
465 struct msgb *msg, uint16_t bvci)
466{
467 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
468 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200469 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200470
471 switch (event) {
472 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200473 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200474 default:
475 break;
476 }
477 return 0;
478}
479
480/* override */
481ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
482 const struct sockaddr *dest_addr, socklen_t addrlen)
483{
484 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
485 const struct sockaddr *, socklen_t);
486 static sendto_t real_sendto = NULL;
487 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200488 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200489
490 if (!real_sendto)
491 real_sendto = dlsym(RTLD_NEXT, "sendto");
492
493 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200494 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
495 dest_host, dest_port,
496 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200497 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200498 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
499 dest_host, dest_port,
500 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200501 else
502 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
503
504 return len;
505}
506
507/* override */
508int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
509{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200510 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
511 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200512 uint16_t bvci = msgb_bvci(msg);
513 uint16_t nsei = msgb_nsei(msg);
514
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200515 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200516
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200517 if (!real_gprs_ns_sendmsg)
518 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
519
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200520 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200521 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
522 "msg length %d (%s)\n",
523 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200524 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200525 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
526 "msg length %d (%s)\n",
527 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200528
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200529 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200530}
531
532static void dump_rate_ctr_group(FILE *stream, const char *prefix,
533 struct rate_ctr_group *ctrg)
534{
535 unsigned int i;
536
537 for (i = 0; i < ctrg->desc->num_ctr; i++) {
538 struct rate_ctr *ctr = &ctrg->ctr[i];
539 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
540 fprintf(stream, " %s%s: %llu%s",
541 prefix, ctrg->desc->ctr_desc[i].description,
542 (long long)ctr->current,
543 "\n");
544 };
545}
546
547/* Signal handler for signals from NS layer */
548static int test_signal(unsigned int subsys, unsigned int signal,
549 void *handler_data, void *signal_data)
550{
551 struct ns_signal_data *nssd = signal_data;
552 int rc;
553
554 if (subsys != SS_L_NS)
555 return 0;
556
557 switch (signal) {
558 case S_NS_RESET:
559 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
560 nssd->nsvc->nsvci,
561 gprs_ns_ll_str(nssd->nsvc));
562 break;
563
564 case S_NS_ALIVE_EXP:
565 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
566 nssd->nsvc->nsvci,
567 gprs_ns_ll_str(nssd->nsvc));
568 break;
569
570 case S_NS_BLOCK:
571 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
572 nssd->nsvc->nsvci,
573 gprs_ns_ll_str(nssd->nsvc));
574 break;
575
576 case S_NS_UNBLOCK:
577 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
578 nssd->nsvc->nsvci,
579 gprs_ns_ll_str(nssd->nsvc));
580 break;
581
582 case S_NS_REPLACED:
583 printf("==> got signal NS_REPLACED: 0x%04x/%s",
584 nssd->nsvc->nsvci,
585 gprs_ns_ll_str(nssd->nsvc));
586 printf(" -> 0x%04x/%s\n",
587 nssd->old_nsvc->nsvci,
588 gprs_ns_ll_str(nssd->old_nsvc));
589 break;
590
591 default:
592 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
593 nssd->nsvc->nsvci,
594 gprs_ns_ll_str(nssd->nsvc));
595 break;
596 }
597 printf("\n");
598 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
599 return rc;
600}
601
602static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
603{
604 struct msgb *msg;
605 int ret;
606 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
607 fprintf(stderr, "message too long: %d\n", data_len);
608 return -1;
609 }
610
611 msg = gprs_ns_msgb_alloc();
612 memmove(msg->data, data, data_len);
613 msg->l2h = msg->data;
614 msgb_put(msg, data_len);
615
616 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
617 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
618 osmo_hexdump(data, data_len));
619
620 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
621
622 printf("result (%s) = %d\n\n", text, ret);
623
624 msgb_free(msg);
625
626 return ret;
627}
628
629static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
630{
631 struct gprs_nsvc *nsvc;
632
633 printf("Current NS-VCIs:\n");
634 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
635 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200636 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200637 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200638 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
639 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
640 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200641 );
642 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
643 }
644 printf("\n");
645}
646
647static void test_gbproxy()
648{
649 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
650 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200651 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200652
653 bssgp_nsi = nsi;
654 gbcfg.nsi = bssgp_nsi;
655 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
656
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200657 configure_sgsn_peer(&sgsn_peer);
658 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200659
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200660 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200661 printf("--- Initialise SGSN ---\n\n");
662
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200663 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200664 gprs_dump_nsi(nsi);
665
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200666 printf("--- Initialise BSS 1 ---\n\n");
667
668 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
669 setup_bssgp(nsi, &bss_peer[0], 0x1002);
670 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200671 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200672
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200673 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
674
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200675 printf("--- Initialise BSS 2 ---\n\n");
676
677 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
678 setup_bssgp(nsi, &bss_peer[1], 0x2002);
679 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200680 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200681
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200682 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
683
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200684 printf("--- Move BSS 1 to new port ---\n\n");
685
686 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
687 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200688 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200689
690 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
691
692 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
693 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200694 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200695
696 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
697
698 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
699 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200700 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200701
702 printf("--- Move BSS 2 to new port ---\n\n");
703
704 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
705 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200706 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200707
708 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
709
710 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
711 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200712 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200713
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200714 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
715
716 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
717 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200718 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200719
720 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
721
722 setup_bssgp(nsi, &bss_peer[0], 0x1012);
723 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200724 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200725
726 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
727
728 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
729
730 setup_bssgp(nsi, &bss_peer[0], 0x1002);
731 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200732 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200733
734 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
735
736 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
737
738 setup_bssgp(nsi, &bss_peer[0], 0x1002);
739 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200740 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200741
742 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
743
744 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
745
746 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
747
748 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
749
750 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
751
752 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
753
754 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
755
756 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
757
758 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
759
760 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
761
762 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
763
764 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
765
766 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
767
768 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
769
770 setup_bssgp(nsi, &bss_peer[2], 0x1002);
771 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200772 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200773
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200774 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200775
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200776 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
777
778 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
779
780 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
781
782 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
783
784 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
785
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200786 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
787
788 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
789
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200790 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200791
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200792 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200793 gprs_ns_destroy(nsi);
794 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200795}
796
797static void test_gbproxy_ident_changes()
798{
799 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
800 struct sockaddr_in bss_peer[1] = {{0},};
801 struct sockaddr_in sgsn_peer= {0};
802 uint16_t nsei[2] = {0x1000, 0x2000};
803 uint16_t nsvci[2] = {0x1001, 0x2001};
804 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
805
806 bssgp_nsi = nsi;
807 gbcfg.nsi = bssgp_nsi;
808 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
809
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200810 configure_sgsn_peer(&sgsn_peer);
811 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200812
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200813 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200814 printf("--- Initialise SGSN ---\n\n");
815
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200816 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200817 gprs_dump_nsi(nsi);
818
819 printf("--- Initialise BSS 1 ---\n\n");
820
821 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
822 gprs_dump_nsi(nsi);
823
824 printf("--- Setup BVCI 1 ---\n\n");
825
826 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
827 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200828 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200829
830 printf("--- Setup BVCI 2 ---\n\n");
831
832 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
833 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200834 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200835
836 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
837
838 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
839 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
840
841 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
842
843 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
844 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
845
846 printf("--- Change NSEI ---\n\n");
847
848 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
849 gprs_dump_nsi(nsi);
850
851 printf("--- Setup BVCI 1 ---\n\n");
852
853 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
854 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200855 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200856
857 printf("--- Setup BVCI 3 ---\n\n");
858
859 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
860 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200861 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200862
863 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
864
865 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
866 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
867
868 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
869 " (should fail) ---\n\n");
870
871 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200872 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200873 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200874 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200875
876 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
877
878 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
879 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
880
881 printf("--- Change NSVCI ---\n\n");
882
883 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
884 gprs_dump_nsi(nsi);
885
886 printf("--- Setup BVCI 1 ---\n\n");
887
888 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
889 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200890 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200891
892 printf("--- Setup BVCI 4 ---\n\n");
893
894 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
895 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200896 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200897
898 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
899
900 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
901 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
902
903 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
904 " (should fail) ---\n\n");
905
906 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200907 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200908 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200909 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200910
911 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
912
913 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
914 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
915
916 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
917
918 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
919 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
920
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200921 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200922 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200923
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200924 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200925 gprs_ns_destroy(nsi);
926 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200927}
928
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200929static void test_gbproxy_ra_patching()
930{
931 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
932 struct sockaddr_in bss_peer[1] = {{0},};
933 struct sockaddr_in sgsn_peer= {0};
934 struct gprs_ra_id rai_bss =
935 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
936 struct gprs_ra_id rai_sgsn =
937 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
938 struct gprs_ra_id rai_unknown =
939 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200940 const char *err_msg = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200941
942 bssgp_nsi = nsi;
943 gbcfg.nsi = bssgp_nsi;
944 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200945 gbcfg.core_mcc = 123;
946 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200947 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200948 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200949
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200950 configure_sgsn_peer(&sgsn_peer);
951 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200952
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200953 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Holger Hans Peter Freyther3fa26442014-08-04 16:27:11 +0200954 if (gbprox_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200955 fprintf(stderr, "Failed to compile RE '%s': %s\n",
956 gbcfg.match_re, err_msg);
957 exit(1);
958 }
959
960
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200961 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200962 printf("--- Initialise SGSN ---\n\n");
963
964 connect_sgsn(nsi, &sgsn_peer);
965 gprs_dump_nsi(nsi);
966
967 printf("--- Initialise BSS 1 ---\n\n");
968
969 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
970 setup_bssgp(nsi, &bss_peer[0], 0x1002);
971 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200972 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200973
974 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
975
976 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
977 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
978
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200979 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200980 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200981
982 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
983
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200984 send_ns_unitdata(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200985 bssgp_attach_req, sizeof(bssgp_attach_req));
986
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200987 send_ns_unitdata(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200988 bssgp_attach_acc, sizeof(bssgp_attach_acc));
989
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +0200990 /* Replace APN (1) */
991 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
992 &bss_peer[0], 0x1002,
993 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200994
Jacob Erlbeck11669742014-06-06 18:47:36 +0200995 send_ns_unitdata(nsi, "GMM INFO", &sgsn_peer, 0x1002,
996 bssgp_gmm_information, sizeof(bssgp_gmm_information));
997
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +0200998 /* Replace APN (2) */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200999 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
1000 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001001 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1002
Jacob Erlbeck73685282014-05-23 20:48:07 +02001003 gbcfg.core_apn[0] = 0;
1004 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001005
1006 /* Remove APN */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001007 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1008 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001009 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1010
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001011 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001012
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001013 /* Detach */
1014 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1015 bssgp_detach_req, sizeof(bssgp_detach_req));
1016
1017 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1018 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1019
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001020 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001021
1022 printf("--- RA update ---\n\n");
1023
1024 send_ns_unitdata(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1025 bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req));
1026
1027 send_ns_unitdata(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1028 bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc));
1029
1030 /* Remove APN */
1031 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1032 &bss_peer[0], 0x1002,
1033 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1034
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001035 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001036
1037 /* Detach */
1038 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1039 bssgp_detach_req, sizeof(bssgp_detach_req));
1040
1041 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1042 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1043
1044
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001045 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001046 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001047
1048 printf("--- Bad cases ---\n\n");
1049
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001050 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001051 send_ns_unitdata(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1052 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1053
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001054 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001055 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1056
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001057 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001058 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001059
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001060 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001061 gprs_ns_destroy(nsi);
1062 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001063}
1064
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001065/* TODO: Move tlv testing to libosmocore */
1066int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1067int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1068 uint8_t **value);
1069int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1070 size_t *value_len);
1071int lv_shift(uint8_t **data, size_t *data_len,
1072 uint8_t **value, size_t *value_len);
1073
1074static void check_tlv_match(uint8_t **data, size_t *data_len,
1075 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1076{
1077 uint8_t *value;
1078 size_t value_len;
1079 int rc;
1080
1081 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1082 OSMO_ASSERT(rc == 0);
1083
1084 rc = tlv_match(data, data_len, tag, &value, &value_len);
1085 OSMO_ASSERT(rc == value_len + 2);
1086 OSMO_ASSERT(value_len == exp_len);
1087 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1088}
1089
1090static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1091 uint8_t tag, size_t len, const uint8_t *exp_val)
1092{
1093 uint8_t *value;
1094 int rc;
1095
1096 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1097 OSMO_ASSERT(rc == 0);
1098
1099 rc = tv_fixed_match(data, data_len, tag, len, &value);
1100 OSMO_ASSERT(rc == len + 1);
1101 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1102}
1103
1104static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1105 size_t len, const uint8_t *exp_val)
1106{
1107 uint8_t *value;
1108 int rc;
1109
1110 rc = v_fixed_shift(data, data_len, len, &value);
1111 OSMO_ASSERT(rc == len);
1112 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1113}
1114
1115static void check_lv_shift(uint8_t **data, size_t *data_len,
1116 size_t exp_len, const uint8_t *exp_val)
1117{
1118 uint8_t *value;
1119 size_t value_len;
1120 int rc;
1121
1122 rc = lv_shift(data, data_len, &value, &value_len);
1123 OSMO_ASSERT(rc == value_len + 1);
1124 OSMO_ASSERT(value_len == exp_len);
1125 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1126}
1127
1128static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1129 const uint8_t *test_data)
1130{
1131 uint8_t buf[300] = {0};
1132
1133 uint8_t *unchanged_ptr = buf - 1;
1134 size_t unchanged_len = 0xdead;
1135 size_t tmp_data_len = data_len;
1136 uint8_t *value = unchanged_ptr;
1137 size_t value_len = unchanged_len;
1138 uint8_t *data = buf;
1139
1140 OSMO_ASSERT(data_len <= sizeof(buf));
1141
1142 tlv_put(data, tag, len, test_data);
1143 if (data_len < len + 2) {
1144 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1145 tag, &value, &value_len));
1146 OSMO_ASSERT(tmp_data_len == 0);
1147 OSMO_ASSERT(data == buf + data_len);
1148 OSMO_ASSERT(value == unchanged_ptr);
1149 OSMO_ASSERT(value_len == unchanged_len);
1150 } else {
1151 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1152 tag, &value, &value_len));
1153 OSMO_ASSERT(value != unchanged_ptr);
1154 OSMO_ASSERT(value_len != unchanged_len);
1155 }
1156}
1157
1158static void check_tv_fixed_match_data_len(size_t data_len,
1159 uint8_t tag, size_t len,
1160 const uint8_t *test_data)
1161{
1162 uint8_t buf[300] = {0};
1163
1164 uint8_t *unchanged_ptr = buf - 1;
1165 size_t tmp_data_len = data_len;
1166 uint8_t *value = unchanged_ptr;
1167 uint8_t *data = buf;
1168
1169 OSMO_ASSERT(data_len <= sizeof(buf));
1170
1171 tv_fixed_put(data, tag, len, test_data);
1172
1173 if (data_len < len + 1) {
1174 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1175 tag, len, &value));
1176 OSMO_ASSERT(tmp_data_len == 0);
1177 OSMO_ASSERT(data == buf + data_len);
1178 OSMO_ASSERT(value == unchanged_ptr);
1179 } else {
1180 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1181 tag, len, &value));
1182 OSMO_ASSERT(value != unchanged_ptr);
1183 }
1184}
1185
1186static void check_v_fixed_shift_data_len(size_t data_len,
1187 size_t len, const uint8_t *test_data)
1188{
1189 uint8_t buf[300] = {0};
1190
1191 uint8_t *unchanged_ptr = buf - 1;
1192 size_t tmp_data_len = data_len;
1193 uint8_t *value = unchanged_ptr;
1194 uint8_t *data = buf;
1195
1196 OSMO_ASSERT(data_len <= sizeof(buf));
1197
1198 memcpy(data, test_data, len);
1199
1200 if (data_len < len) {
1201 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1202 len, &value));
1203 OSMO_ASSERT(tmp_data_len == 0);
1204 OSMO_ASSERT(data == buf + data_len);
1205 OSMO_ASSERT(value == unchanged_ptr);
1206 } else {
1207 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1208 len, &value));
1209 OSMO_ASSERT(value != unchanged_ptr);
1210 }
1211}
1212
1213static void check_lv_shift_data_len(size_t data_len,
1214 size_t len, const uint8_t *test_data)
1215{
1216 uint8_t buf[300] = {0};
1217
1218 uint8_t *unchanged_ptr = buf - 1;
1219 size_t unchanged_len = 0xdead;
1220 size_t tmp_data_len = data_len;
1221 uint8_t *value = unchanged_ptr;
1222 size_t value_len = unchanged_len;
1223 uint8_t *data = buf;
1224
1225 lv_put(data, len, test_data);
1226 if (data_len < len + 1) {
1227 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1228 &value, &value_len));
1229 OSMO_ASSERT(tmp_data_len == 0);
1230 OSMO_ASSERT(data == buf + data_len);
1231 OSMO_ASSERT(value == unchanged_ptr);
1232 OSMO_ASSERT(value_len == unchanged_len);
1233 } else {
1234 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1235 &value, &value_len));
1236 OSMO_ASSERT(value != unchanged_ptr);
1237 OSMO_ASSERT(value_len != unchanged_len);
1238 }
1239}
1240
1241static void test_tlv_shift_functions()
1242{
1243 uint8_t test_data[1024];
1244 uint8_t buf[1024];
1245 uint8_t *data_end;
1246 int i, len;
1247 uint8_t *data;
1248 size_t data_len;
1249 const uint8_t tag = 0x1a;
1250
1251 printf("Test shift functions\n");
1252
1253 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1254 test_data[i] = (uint8_t)i;
1255
1256 for (len = 0; len < 256; len++) {
1257 const int iterations = sizeof(buf) / (len + 2) / 4;
1258
1259 memset(buf, 0xee, sizeof(buf));
1260 data_end = data = buf;
1261
1262 for (i = 0; i < iterations; i++) {
1263 data_end = tlv_put(data_end, tag, len, test_data);
1264 data_end = tv_fixed_put(data_end, tag, len, test_data);
1265 /* v_fixed_put */
1266 memcpy(data_end, test_data, len);
1267 data_end += len;
1268 data_end = lv_put(data_end, len, test_data);
1269 }
1270
1271 data_len = data_end - data;
1272 OSMO_ASSERT(data_len <= sizeof(buf));
1273
1274 for (i = 0; i < iterations; i++) {
1275 check_tlv_match(&data, &data_len, tag, len, test_data);
1276 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1277 check_v_fixed_shift(&data, &data_len, len, test_data);
1278 check_lv_shift(&data, &data_len, len, test_data);
1279 }
1280
1281 OSMO_ASSERT(data == data_end);
1282
1283 /* Test at end of data */
1284
1285 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1286 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1287 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1288 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1289
1290 /* Test invalid data_len */
1291 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1292 check_tlv_match_data_len(data_len, tag, len, test_data);
1293 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1294 check_v_fixed_shift_data_len(data_len, len, test_data);
1295 check_lv_shift_data_len(data_len, len, test_data);
1296 }
1297 }
1298}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001299
1300static void test_gbproxy_tlli_expire(void)
1301{
1302 struct gbproxy_config cfg = {0};
1303 struct gbproxy_peer *peer;
1304 const char *err_msg = NULL;
1305 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1306 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
1307 const uint32_t tlli1 = 1234 | 0xc0000000;
1308 const uint32_t tlli2 = 5678 | 0xc0000000;
1309 const char *filter_re = ".*";
1310
1311 printf("Test TLLI info expiry\n\n");
1312
1313 gbproxy_init_config(&cfg);
1314
1315 if (gbprox_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
1316 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1317 err_msg);
1318 OSMO_ASSERT(err_msg == NULL);
1319 }
1320
1321 {
1322 struct gbproxy_tlli_info *tlli_info;
1323
1324 printf("Test TLLI replacement:\n");
1325
1326 cfg.tlli_max_len = 0;
1327 cfg.tlli_max_age = 0;
1328 peer = gbproxy_peer_alloc(&cfg, 20);
1329 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1330
1331 printf(" Add TLLI 1, IMSI 1\n");
1332 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1333 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1334
1335 /* replace the old entry */
1336 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
1337 gbprox_register_tlli(peer, tlli2, imsi1, ARRAY_SIZE(imsi1));
1338 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1339
1340 dump_peers(stdout, 2, &cfg);
1341
1342 /* verify that 5678 has survived */
1343 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1344 OSMO_ASSERT(tlli_info);
1345 OSMO_ASSERT(tlli_info->tlli == tlli2);
1346 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1347 OSMO_ASSERT(!tlli_info);
1348
1349 printf("\n");
1350
1351 gbproxy_peer_free(peer);
1352 }
1353
1354 {
1355 struct gbproxy_tlli_info *tlli_info;
1356
1357 printf("Test IMSI replacement:\n");
1358
1359 cfg.tlli_max_len = 0;
1360 cfg.tlli_max_age = 0;
1361 peer = gbproxy_peer_alloc(&cfg, 20);
1362 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1363
1364 printf(" Add TLLI 1, IMSI 1\n");
1365 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1366 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1367
1368 /* try to replace the old entry */
1369 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
1370 gbprox_register_tlli(peer, tlli1, imsi2, ARRAY_SIZE(imsi2));
1371 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1372
1373 dump_peers(stdout, 2, &cfg);
1374
1375 /* verify that 5678 has survived */
1376 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1377 OSMO_ASSERT(!tlli_info);
1378 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1379 OSMO_ASSERT(tlli_info);
1380 OSMO_ASSERT(tlli_info->tlli == tlli1);
1381
1382 printf("\n");
1383
1384 gbproxy_peer_free(peer);
1385 }
1386
1387 {
1388 struct gbproxy_tlli_info *tlli_info;
1389
1390 printf("Test TLLI expiry, max_len == 1:\n");
1391
1392 cfg.tlli_max_len = 1;
1393 cfg.tlli_max_age = 0;
1394 peer = gbproxy_peer_alloc(&cfg, 20);
1395 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1396
1397 printf(" Add TLLI 1, IMSI 1\n");
1398 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1399 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1400
1401 /* replace the old entry */
1402 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
1403 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2));
1404 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1405
1406 dump_peers(stdout, 2, &cfg);
1407
1408 /* verify that 5678 has survived */
1409 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1410 OSMO_ASSERT(!tlli_info);
1411 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1412 OSMO_ASSERT(tlli_info);
1413 OSMO_ASSERT(tlli_info->tlli == tlli2);
1414
1415 printf("\n");
1416
1417 gbproxy_peer_free(peer);
1418 }
1419
1420 {
1421 int ret;
1422
1423 printf("Test TLLI expiry, max_age == 1:\n");
1424
1425 cfg.tlli_max_len = 0;
1426 cfg.tlli_max_age = 1;
1427 peer = gbproxy_peer_alloc(&cfg, 20);
1428 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1429
1430 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
1431 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1432 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1433
1434 /* replace the old entry */
1435 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
1436 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2));
1437 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1438
1439 ret = gbprox_remove_stale_tllis(peer, time(NULL) + 2);
1440 OSMO_ASSERT(ret == 2);
1441 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1442
1443 dump_peers(stdout, 2, &cfg);
1444
1445 printf("\n");
1446
1447 gbproxy_peer_free(peer);
1448 }
1449}
1450
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001451static struct log_info_cat gprs_categories[] = {
1452 [DGPRS] = {
1453 .name = "DGPRS",
1454 .description = "GPRS Packet Service",
1455 .enabled = 1, .loglevel = LOGL_DEBUG,
1456 },
1457 [DNS] = {
1458 .name = "DNS",
1459 .description = "GPRS Network Service (NS)",
1460 .enabled = 1, .loglevel = LOGL_INFO,
1461 },
1462 [DBSSGP] = {
1463 .name = "DBSSGP",
1464 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1465 .enabled = 1, .loglevel = LOGL_DEBUG,
1466 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001467};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001468
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001469static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001470 .cat = gprs_categories,
1471 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001472};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001473
1474int main(int argc, char **argv)
1475{
1476 osmo_init_logging(&info);
1477 log_set_use_color(osmo_stderr_target, 0);
1478 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001479 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001480
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001481 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001482 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1483 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001484
1485 rate_ctr_init(NULL);
1486
1487 setlinebuf(stdout);
1488
1489 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02001490 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001491 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001492 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001493 test_gbproxy_ident_changes();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001494 test_gbproxy_ra_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001495 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001496 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001497
1498 exit(EXIT_SUCCESS);
1499}