blob: 39800aae1ad03acc315e805a9e7b213e52dab630 [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
Jacob Erlbeck7b821d02014-08-08 08:37:37 +020071static int dump_peers(FILE *stream, int indent, time_t now,
72 struct gbproxy_config *cfg)
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020073{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020074 struct gbproxy_peer *peer;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020075 struct gprs_ra_id raid;
76 unsigned int i;
77 const struct rate_ctr_group_desc *desc;
78 int rc;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020079
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];
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200118 time_t age = now ? now - tlli_info->timestamp : 0;
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200119 if (tlli_info->mi_data_len > 0) {
120 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
121 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
122 tlli_info->mi_data,
123 tlli_info->mi_data_len);
124 } else {
125 snprintf(mi_buf, sizeof(mi_buf), "(none)");
126 }
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200127 rc = fprintf(stream,
128 "%*s TLLI %08x, IMSI %s, AGE %d\n",
129 indent, "",
130 tlli_info->tlli, mi_buf, (int)age);
131 if (rc < 0)
132 return rc;
133 }
134 }
135
136 return 0;
137}
138
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200139/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Request */
140static const unsigned char bssgp_attach_req[75] = {
141 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
142 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
143 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x34, 0x01,
144 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21,
145 0x08, 0x02, 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79,
146 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19, 0x18,
147 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
148 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80,
149 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
150 0x16, 0x6d, 0x01
151};
152
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200153/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Request */
154static const unsigned char bssgp_identity_req[] = {
155 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
156 0x16, 0x82, 0x02, 0x58, 0x0e, 0x89, 0x41, 0xc0,
157 0x01, 0x08, 0x15, 0x01, 0xff, 0x6c, 0xba
158};
159
160/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Response */
161static const unsigned char bssgp_identity_resp[] = {
162 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
163 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
164 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x11, 0x01,
165 0xc0, 0x0d, 0x08, 0x16, 0x08, 0x11, 0x12, 0x13,
166 0x14, 0x15, 0x16, 0x17, 0x18, 0xb7, 0x1b, 0x9a
167};
168
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200169/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */
170static const unsigned char bssgp_attach_acc[88] = {
171 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
172 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
173 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
174 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
175 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
176 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
177 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
178 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01,
179 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60,
180 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05,
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +0200181 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x42, 0x67, 0x9a
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200182};
183
Jacob Erlbeck11669742014-06-06 18:47:36 +0200184/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - GMM Information */
185static const unsigned char bssgp_gmm_information[66] = {
186 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
187 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
188 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
189 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
190 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
191 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
192 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
193 0x0e, 0x88, 0x41, 0xc0, 0x09, 0x08, 0x21, 0x04,
194 0xba, 0x3d
195};
196
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200197/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */
198static const unsigned char bssgp_ra_upd_req[85] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200199 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200200 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
201 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01,
202 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33,
203 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33,
204 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48,
205 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8,
206 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02,
207 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27,
208 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02,
209 0x20, 0x00, 0x96, 0x3e, 0x97
210};
211
212/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */
213static const unsigned char bssgp_ra_upd_acc[91] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200214 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200215 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13,
216 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02,
217 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48,
218 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8,
219 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d,
220 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
221 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0,
222 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
223 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
224 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16,
225 0xc3, 0xbf, 0xcc
226};
227
228/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */
229static const unsigned char bssgp_act_pdp_ctx_req[76] = {
230 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
231 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
232 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01,
233 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
234 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
236 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
237 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
238 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
239 0x00, 0x5a, 0xff, 0x02
240};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200241
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200242/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Request */
243static const unsigned char bssgp_detach_req[44] = {
244 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
245 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
246 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x15, 0x01,
247 0xc0, 0x19, 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4,
248 0xef, 0xe2, 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97,
249 0xcb, 0x7e, 0xe1, 0x41
250};
251
252/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Accept */
253static const unsigned char bssgp_detach_acc[67] = {
254 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
255 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
256 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
257 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
258 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
259 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
260 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
261 0x0e, 0x89, 0x41, 0xc0, 0x15, 0x08, 0x06, 0x00,
262 0xf7, 0x35, 0xf0
263};
264
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200265static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
266 struct sockaddr_in *peer, const unsigned char* data,
267 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200268
269static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
270 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
271{
272 /* GPRS Network Service, PDU type: NS_RESET,
273 */
274 unsigned char msg[12] = {
275 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
276 0x04, 0x82, 0x11, 0x22
277 };
278
279 msg[3] = cause;
280 msg[6] = nsvci / 256;
281 msg[7] = nsvci % 256;
282 msg[10] = nsei / 256;
283 msg[11] = nsei % 256;
284
285 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
286}
287
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200288static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
289 uint16_t nsvci, uint16_t nsei)
290{
291 /* GPRS Network Service, PDU type: NS_RESET_ACK,
292 */
293 unsigned char msg[9] = {
294 0x03, 0x01, 0x82, 0x11, 0x22,
295 0x04, 0x82, 0x11, 0x22
296 };
297
298 msg[3] = nsvci / 256;
299 msg[4] = nsvci % 256;
300 msg[7] = nsei / 256;
301 msg[8] = nsei % 256;
302
303 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
304}
305
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200306static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
307{
308 /* GPRS Network Service, PDU type: NS_ALIVE */
309 unsigned char msg[1] = {
310 0x0a
311 };
312
313 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
314}
315
316static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
317{
318 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
319 unsigned char msg[1] = {
320 0x0b
321 };
322
323 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
324}
325
326static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
327{
328 /* GPRS Network Service, PDU type: NS_UNBLOCK */
329 unsigned char msg[1] = {
330 0x06
331 };
332
333 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
334}
335
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200336static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
337{
338 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
339 unsigned char msg[1] = {
340 0x07
341 };
342
343 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
344}
345
346static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
347 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200348 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
349{
350 /* GPRS Network Service, PDU type: NS_UNITDATA */
351 unsigned char msg[4096] = {
352 0x00, 0x00, 0x00, 0x00
353 };
354
355 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
356
357 msg[2] = nsbvci / 256;
358 msg[3] = nsbvci % 256;
359 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
360
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200361 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200362}
363
364static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
365 uint16_t bvci)
366{
367 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
368 * BSSGP RESET */
Jacob Erlbeckda4b4922014-08-06 12:38:10 +0200369 unsigned char msg[18] = {
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200370 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200371 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
372 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200373 };
374
375 msg[3] = bvci / 256;
376 msg[4] = bvci % 256;
377
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200378 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
379}
380
381static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
382 struct sockaddr_in *src_addr, uint16_t bvci)
383{
384 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
385 * BSSGP RESET_ACK */
386 static unsigned char msg[5] = {
387 0x23, 0x04, 0x82, 0x00,
388 0x00
389 };
390
391 msg[3] = bvci / 256;
392 msg[4] = bvci % 256;
393
394 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200395}
396
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200397static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
398 struct sockaddr_in *src_addr,
399 struct gprs_ra_id *raid)
400{
401 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
402 unsigned char msg[15] = {
403 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
404 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
405 };
406
407 gsm48_construct_ra(msg + 9, raid);
408
409 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
410}
411
412static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
413 struct sockaddr_in *src_addr,
414 struct gprs_ra_id *raid)
415{
416 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
417 unsigned char msg[18] = {
418 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
419 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
420 0x81, 0x01
421 };
422
423 gsm48_construct_ra(msg + 9, raid);
424
425 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
426}
427
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200428static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
429 uint16_t nsvci, uint16_t nsei)
430{
431 printf("Setup NS-VC: remote 0x%08x:%d, "
432 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
433 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
434 nsvci, nsvci, nsei, nsei);
435
436 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
437 send_ns_alive(nsi, src_addr);
438 send_ns_unblock(nsi, src_addr);
439 send_ns_alive_ack(nsi, src_addr);
440}
441
442static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
443 uint16_t bvci)
444{
445 printf("Setup BSSGP: remote 0x%08x:%d, "
446 "BVCI 0x%04x(%d)\n\n",
447 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
448 bvci, bvci);
449
450 send_bssgp_reset(nsi, src_addr, bvci);
451}
452
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200453static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
454{
455 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
456 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
457 send_ns_alive_ack(nsi, sgsn_peer);
458 send_ns_unblock_ack(nsi, sgsn_peer);
459 send_ns_alive(nsi, sgsn_peer);
460}
461
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200462static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
463{
464 sgsn_peer->sin_family = AF_INET;
465 sgsn_peer->sin_port = htons(32000);
466 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
467}
468
469static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
470{
471 size_t i;
472
473 for (i = 0; i < size; ++i) {
474 bss_peers[i].sin_family = AF_INET;
475 bss_peers[i].sin_port = htons((i + 1) * 1111);
476 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
477 }
478}
479
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200480int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
481 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
482
483/* override */
484int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
485 struct msgb *msg, uint16_t bvci)
486{
487 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
488 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200489 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200490
491 switch (event) {
492 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200493 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200494 default:
495 break;
496 }
497 return 0;
498}
499
500/* override */
501ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
502 const struct sockaddr *dest_addr, socklen_t addrlen)
503{
504 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
505 const struct sockaddr *, socklen_t);
506 static sendto_t real_sendto = NULL;
507 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200508 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200509
510 if (!real_sendto)
511 real_sendto = dlsym(RTLD_NEXT, "sendto");
512
513 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200514 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
515 dest_host, dest_port,
516 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200517 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200518 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
519 dest_host, dest_port,
520 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200521 else
522 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
523
524 return len;
525}
526
527/* override */
528int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
529{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200530 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
531 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200532 uint16_t bvci = msgb_bvci(msg);
533 uint16_t nsei = msgb_nsei(msg);
534
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200535 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200536
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200537 if (!real_gprs_ns_sendmsg)
538 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
539
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200540 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200541 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
542 "msg length %d (%s)\n",
543 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200544 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200545 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
546 "msg length %d (%s)\n",
547 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200548
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200549 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200550}
551
552static void dump_rate_ctr_group(FILE *stream, const char *prefix,
553 struct rate_ctr_group *ctrg)
554{
555 unsigned int i;
556
557 for (i = 0; i < ctrg->desc->num_ctr; i++) {
558 struct rate_ctr *ctr = &ctrg->ctr[i];
559 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
560 fprintf(stream, " %s%s: %llu%s",
561 prefix, ctrg->desc->ctr_desc[i].description,
562 (long long)ctr->current,
563 "\n");
564 };
565}
566
567/* Signal handler for signals from NS layer */
568static int test_signal(unsigned int subsys, unsigned int signal,
569 void *handler_data, void *signal_data)
570{
571 struct ns_signal_data *nssd = signal_data;
572 int rc;
573
574 if (subsys != SS_L_NS)
575 return 0;
576
577 switch (signal) {
578 case S_NS_RESET:
579 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
580 nssd->nsvc->nsvci,
581 gprs_ns_ll_str(nssd->nsvc));
582 break;
583
584 case S_NS_ALIVE_EXP:
585 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
586 nssd->nsvc->nsvci,
587 gprs_ns_ll_str(nssd->nsvc));
588 break;
589
590 case S_NS_BLOCK:
591 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
592 nssd->nsvc->nsvci,
593 gprs_ns_ll_str(nssd->nsvc));
594 break;
595
596 case S_NS_UNBLOCK:
597 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
598 nssd->nsvc->nsvci,
599 gprs_ns_ll_str(nssd->nsvc));
600 break;
601
602 case S_NS_REPLACED:
603 printf("==> got signal NS_REPLACED: 0x%04x/%s",
604 nssd->nsvc->nsvci,
605 gprs_ns_ll_str(nssd->nsvc));
606 printf(" -> 0x%04x/%s\n",
607 nssd->old_nsvc->nsvci,
608 gprs_ns_ll_str(nssd->old_nsvc));
609 break;
610
611 default:
612 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
613 nssd->nsvc->nsvci,
614 gprs_ns_ll_str(nssd->nsvc));
615 break;
616 }
617 printf("\n");
618 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
619 return rc;
620}
621
622static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
623{
624 struct msgb *msg;
625 int ret;
626 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
627 fprintf(stderr, "message too long: %d\n", data_len);
628 return -1;
629 }
630
631 msg = gprs_ns_msgb_alloc();
632 memmove(msg->data, data, data_len);
633 msg->l2h = msg->data;
634 msgb_put(msg, data_len);
635
636 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
637 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
638 osmo_hexdump(data, data_len));
639
640 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
641
642 printf("result (%s) = %d\n\n", text, ret);
643
644 msgb_free(msg);
645
646 return ret;
647}
648
649static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
650{
651 struct gprs_nsvc *nsvc;
652
653 printf("Current NS-VCIs:\n");
654 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
655 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200656 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200657 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200658 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
659 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
660 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200661 );
662 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
663 }
664 printf("\n");
665}
666
667static void test_gbproxy()
668{
669 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
670 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200671 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200672
673 bssgp_nsi = nsi;
674 gbcfg.nsi = bssgp_nsi;
675 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
676
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200677 configure_sgsn_peer(&sgsn_peer);
678 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200679
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200680 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200681 printf("--- Initialise SGSN ---\n\n");
682
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200683 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200684 gprs_dump_nsi(nsi);
685
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200686 printf("--- Initialise BSS 1 ---\n\n");
687
688 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
689 setup_bssgp(nsi, &bss_peer[0], 0x1002);
690 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200691 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200692
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200693 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
694
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200695 printf("--- Initialise BSS 2 ---\n\n");
696
697 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
698 setup_bssgp(nsi, &bss_peer[1], 0x2002);
699 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200700 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200701
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200702 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
703
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200704 printf("--- Move BSS 1 to new port ---\n\n");
705
706 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
707 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200708 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200709
710 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
711
712 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
713 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200714 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200715
716 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
717
718 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
719 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200720 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200721
722 printf("--- Move BSS 2 to new port ---\n\n");
723
724 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
725 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200726 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200727
728 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
729
730 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
731 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200732 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200733
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200734 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
735
736 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
737 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200738 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200739
740 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
741
742 setup_bssgp(nsi, &bss_peer[0], 0x1012);
743 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200744 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200745
746 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
747
748 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
749
750 setup_bssgp(nsi, &bss_peer[0], 0x1002);
751 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200752 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200753
754 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
755
756 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
757
758 setup_bssgp(nsi, &bss_peer[0], 0x1002);
759 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200760 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200761
762 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
763
764 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
765
766 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
767
768 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
769
770 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
771
772 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
773
774 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
775
776 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
777
778 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
779
780 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
781
782 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
783
784 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
785
786 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
787
788 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
789
790 setup_bssgp(nsi, &bss_peer[2], 0x1002);
791 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200792 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200793
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200794 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200795
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200796 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
797
798 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
799
800 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
801
802 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
803
804 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
805
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200806 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
807
808 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
809
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200810 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200811
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200812 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200813 gprs_ns_destroy(nsi);
814 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200815}
816
817static void test_gbproxy_ident_changes()
818{
819 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
820 struct sockaddr_in bss_peer[1] = {{0},};
821 struct sockaddr_in sgsn_peer= {0};
822 uint16_t nsei[2] = {0x1000, 0x2000};
823 uint16_t nsvci[2] = {0x1001, 0x2001};
824 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
825
826 bssgp_nsi = nsi;
827 gbcfg.nsi = bssgp_nsi;
828 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
829
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200830 configure_sgsn_peer(&sgsn_peer);
831 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200832
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200833 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200834 printf("--- Initialise SGSN ---\n\n");
835
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200836 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200837 gprs_dump_nsi(nsi);
838
839 printf("--- Initialise BSS 1 ---\n\n");
840
841 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
842 gprs_dump_nsi(nsi);
843
844 printf("--- Setup BVCI 1 ---\n\n");
845
846 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
847 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200848 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200849
850 printf("--- Setup BVCI 2 ---\n\n");
851
852 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
853 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200854 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200855
856 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
857
858 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
859 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
860
861 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
862
863 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
864 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
865
866 printf("--- Change NSEI ---\n\n");
867
868 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
869 gprs_dump_nsi(nsi);
870
871 printf("--- Setup BVCI 1 ---\n\n");
872
873 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
874 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200875 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200876
877 printf("--- Setup BVCI 3 ---\n\n");
878
879 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
880 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200881 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200882
883 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
884
885 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
886 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
887
888 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
889 " (should fail) ---\n\n");
890
891 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200892 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200893 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200894 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200895
896 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
897
898 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
899 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
900
901 printf("--- Change NSVCI ---\n\n");
902
903 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
904 gprs_dump_nsi(nsi);
905
906 printf("--- Setup BVCI 1 ---\n\n");
907
908 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
909 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200910 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200911
912 printf("--- Setup BVCI 4 ---\n\n");
913
914 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
915 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200916 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200917
918 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
919
920 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
921 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
922
923 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
924 " (should fail) ---\n\n");
925
926 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200927 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200928 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200929 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200930
931 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
932
933 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
934 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
935
936 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
937
938 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
939 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
940
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200941 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200942 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200943
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200944 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200945 gprs_ns_destroy(nsi);
946 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200947}
948
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200949static void test_gbproxy_ra_patching()
950{
951 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
952 struct sockaddr_in bss_peer[1] = {{0},};
953 struct sockaddr_in sgsn_peer= {0};
954 struct gprs_ra_id rai_bss =
955 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
956 struct gprs_ra_id rai_sgsn =
957 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
958 struct gprs_ra_id rai_unknown =
959 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200960 const char *err_msg = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200961
962 bssgp_nsi = nsi;
963 gbcfg.nsi = bssgp_nsi;
964 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200965 gbcfg.core_mcc = 123;
966 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200967 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200968 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200969
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200970 configure_sgsn_peer(&sgsn_peer);
971 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200972
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200973 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Holger Hans Peter Freyther3fa26442014-08-04 16:27:11 +0200974 if (gbprox_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200975 fprintf(stderr, "Failed to compile RE '%s': %s\n",
976 gbcfg.match_re, err_msg);
977 exit(1);
978 }
979
980
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200981 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200982 printf("--- Initialise SGSN ---\n\n");
983
984 connect_sgsn(nsi, &sgsn_peer);
985 gprs_dump_nsi(nsi);
986
987 printf("--- Initialise BSS 1 ---\n\n");
988
989 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
990 setup_bssgp(nsi, &bss_peer[0], 0x1002);
991 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200992 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200993
994 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
995
996 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
997 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
998
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200999 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001000 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001001
1002 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1003
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001004 send_ns_unitdata(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001005 bssgp_attach_req, sizeof(bssgp_attach_req));
1006
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001007 send_ns_unitdata(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1008 bssgp_identity_req, sizeof(bssgp_identity_req));
1009
1010 send_ns_unitdata(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1011 bssgp_identity_resp, sizeof(bssgp_identity_resp));
1012
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001013 send_ns_unitdata(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001014 bssgp_attach_acc, sizeof(bssgp_attach_acc));
1015
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001016 /* Replace APN (1) */
1017 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
1018 &bss_peer[0], 0x1002,
1019 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001020
Jacob Erlbeck11669742014-06-06 18:47:36 +02001021 send_ns_unitdata(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1022 bssgp_gmm_information, sizeof(bssgp_gmm_information));
1023
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001024 /* Replace APN (2) */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001025 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
1026 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001027 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1028
Jacob Erlbeck73685282014-05-23 20:48:07 +02001029 gbcfg.core_apn[0] = 0;
1030 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001031
1032 /* Remove APN */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001033 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1034 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001035 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1036
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001037 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001038
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001039 /* Detach */
1040 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1041 bssgp_detach_req, sizeof(bssgp_detach_req));
1042
1043 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1044 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1045
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001046 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001047
1048 printf("--- RA update ---\n\n");
1049
1050 send_ns_unitdata(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1051 bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req));
1052
1053 send_ns_unitdata(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1054 bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc));
1055
1056 /* Remove APN */
1057 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1058 &bss_peer[0], 0x1002,
1059 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1060
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001061 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001062
1063 /* Detach */
1064 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1065 bssgp_detach_req, sizeof(bssgp_detach_req));
1066
1067 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1068 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1069
1070
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001071 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001072 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001073
1074 printf("--- Bad cases ---\n\n");
1075
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001076 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001077 send_ns_unitdata(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1078 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1079
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001080 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001081 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1082
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001083 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001084 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001085
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001086 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001087 gprs_ns_destroy(nsi);
1088 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001089}
1090
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001091/* TODO: Move tlv testing to libosmocore */
1092int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1093int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1094 uint8_t **value);
1095int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1096 size_t *value_len);
1097int lv_shift(uint8_t **data, size_t *data_len,
1098 uint8_t **value, size_t *value_len);
1099
1100static void check_tlv_match(uint8_t **data, size_t *data_len,
1101 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1102{
1103 uint8_t *value;
1104 size_t value_len;
1105 int rc;
1106
1107 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1108 OSMO_ASSERT(rc == 0);
1109
1110 rc = tlv_match(data, data_len, tag, &value, &value_len);
1111 OSMO_ASSERT(rc == value_len + 2);
1112 OSMO_ASSERT(value_len == exp_len);
1113 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1114}
1115
1116static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1117 uint8_t tag, size_t len, const uint8_t *exp_val)
1118{
1119 uint8_t *value;
1120 int rc;
1121
1122 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1123 OSMO_ASSERT(rc == 0);
1124
1125 rc = tv_fixed_match(data, data_len, tag, len, &value);
1126 OSMO_ASSERT(rc == len + 1);
1127 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1128}
1129
1130static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1131 size_t len, const uint8_t *exp_val)
1132{
1133 uint8_t *value;
1134 int rc;
1135
1136 rc = v_fixed_shift(data, data_len, len, &value);
1137 OSMO_ASSERT(rc == len);
1138 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1139}
1140
1141static void check_lv_shift(uint8_t **data, size_t *data_len,
1142 size_t exp_len, const uint8_t *exp_val)
1143{
1144 uint8_t *value;
1145 size_t value_len;
1146 int rc;
1147
1148 rc = lv_shift(data, data_len, &value, &value_len);
1149 OSMO_ASSERT(rc == value_len + 1);
1150 OSMO_ASSERT(value_len == exp_len);
1151 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1152}
1153
1154static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1155 const uint8_t *test_data)
1156{
1157 uint8_t buf[300] = {0};
1158
1159 uint8_t *unchanged_ptr = buf - 1;
1160 size_t unchanged_len = 0xdead;
1161 size_t tmp_data_len = data_len;
1162 uint8_t *value = unchanged_ptr;
1163 size_t value_len = unchanged_len;
1164 uint8_t *data = buf;
1165
1166 OSMO_ASSERT(data_len <= sizeof(buf));
1167
1168 tlv_put(data, tag, len, test_data);
1169 if (data_len < len + 2) {
1170 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1171 tag, &value, &value_len));
1172 OSMO_ASSERT(tmp_data_len == 0);
1173 OSMO_ASSERT(data == buf + data_len);
1174 OSMO_ASSERT(value == unchanged_ptr);
1175 OSMO_ASSERT(value_len == unchanged_len);
1176 } else {
1177 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1178 tag, &value, &value_len));
1179 OSMO_ASSERT(value != unchanged_ptr);
1180 OSMO_ASSERT(value_len != unchanged_len);
1181 }
1182}
1183
1184static void check_tv_fixed_match_data_len(size_t data_len,
1185 uint8_t tag, size_t len,
1186 const uint8_t *test_data)
1187{
1188 uint8_t buf[300] = {0};
1189
1190 uint8_t *unchanged_ptr = buf - 1;
1191 size_t tmp_data_len = data_len;
1192 uint8_t *value = unchanged_ptr;
1193 uint8_t *data = buf;
1194
1195 OSMO_ASSERT(data_len <= sizeof(buf));
1196
1197 tv_fixed_put(data, tag, len, test_data);
1198
1199 if (data_len < len + 1) {
1200 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1201 tag, len, &value));
1202 OSMO_ASSERT(tmp_data_len == 0);
1203 OSMO_ASSERT(data == buf + data_len);
1204 OSMO_ASSERT(value == unchanged_ptr);
1205 } else {
1206 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1207 tag, len, &value));
1208 OSMO_ASSERT(value != unchanged_ptr);
1209 }
1210}
1211
1212static void check_v_fixed_shift_data_len(size_t data_len,
1213 size_t len, const uint8_t *test_data)
1214{
1215 uint8_t buf[300] = {0};
1216
1217 uint8_t *unchanged_ptr = buf - 1;
1218 size_t tmp_data_len = data_len;
1219 uint8_t *value = unchanged_ptr;
1220 uint8_t *data = buf;
1221
1222 OSMO_ASSERT(data_len <= sizeof(buf));
1223
1224 memcpy(data, test_data, len);
1225
1226 if (data_len < len) {
1227 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1228 len, &value));
1229 OSMO_ASSERT(tmp_data_len == 0);
1230 OSMO_ASSERT(data == buf + data_len);
1231 OSMO_ASSERT(value == unchanged_ptr);
1232 } else {
1233 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1234 len, &value));
1235 OSMO_ASSERT(value != unchanged_ptr);
1236 }
1237}
1238
1239static void check_lv_shift_data_len(size_t data_len,
1240 size_t len, const uint8_t *test_data)
1241{
1242 uint8_t buf[300] = {0};
1243
1244 uint8_t *unchanged_ptr = buf - 1;
1245 size_t unchanged_len = 0xdead;
1246 size_t tmp_data_len = data_len;
1247 uint8_t *value = unchanged_ptr;
1248 size_t value_len = unchanged_len;
1249 uint8_t *data = buf;
1250
1251 lv_put(data, len, test_data);
1252 if (data_len < len + 1) {
1253 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1254 &value, &value_len));
1255 OSMO_ASSERT(tmp_data_len == 0);
1256 OSMO_ASSERT(data == buf + data_len);
1257 OSMO_ASSERT(value == unchanged_ptr);
1258 OSMO_ASSERT(value_len == unchanged_len);
1259 } else {
1260 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1261 &value, &value_len));
1262 OSMO_ASSERT(value != unchanged_ptr);
1263 OSMO_ASSERT(value_len != unchanged_len);
1264 }
1265}
1266
1267static void test_tlv_shift_functions()
1268{
1269 uint8_t test_data[1024];
1270 uint8_t buf[1024];
1271 uint8_t *data_end;
1272 int i, len;
1273 uint8_t *data;
1274 size_t data_len;
1275 const uint8_t tag = 0x1a;
1276
1277 printf("Test shift functions\n");
1278
1279 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1280 test_data[i] = (uint8_t)i;
1281
1282 for (len = 0; len < 256; len++) {
1283 const int iterations = sizeof(buf) / (len + 2) / 4;
1284
1285 memset(buf, 0xee, sizeof(buf));
1286 data_end = data = buf;
1287
1288 for (i = 0; i < iterations; i++) {
1289 data_end = tlv_put(data_end, tag, len, test_data);
1290 data_end = tv_fixed_put(data_end, tag, len, test_data);
1291 /* v_fixed_put */
1292 memcpy(data_end, test_data, len);
1293 data_end += len;
1294 data_end = lv_put(data_end, len, test_data);
1295 }
1296
1297 data_len = data_end - data;
1298 OSMO_ASSERT(data_len <= sizeof(buf));
1299
1300 for (i = 0; i < iterations; i++) {
1301 check_tlv_match(&data, &data_len, tag, len, test_data);
1302 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1303 check_v_fixed_shift(&data, &data_len, len, test_data);
1304 check_lv_shift(&data, &data_len, len, test_data);
1305 }
1306
1307 OSMO_ASSERT(data == data_end);
1308
1309 /* Test at end of data */
1310
1311 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1312 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1313 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1314 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1315
1316 /* Test invalid data_len */
1317 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1318 check_tlv_match_data_len(data_len, tag, len, test_data);
1319 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1320 check_v_fixed_shift_data_len(data_len, len, test_data);
1321 check_lv_shift_data_len(data_len, len, test_data);
1322 }
1323 }
1324}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001325
1326static void test_gbproxy_tlli_expire(void)
1327{
1328 struct gbproxy_config cfg = {0};
1329 struct gbproxy_peer *peer;
1330 const char *err_msg = NULL;
1331 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1332 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
1333 const uint32_t tlli1 = 1234 | 0xc0000000;
1334 const uint32_t tlli2 = 5678 | 0xc0000000;
1335 const char *filter_re = ".*";
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001336 time_t now = 1407479214;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001337
1338 printf("Test TLLI info expiry\n\n");
1339
1340 gbproxy_init_config(&cfg);
1341
1342 if (gbprox_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
1343 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1344 err_msg);
1345 OSMO_ASSERT(err_msg == NULL);
1346 }
1347
1348 {
1349 struct gbproxy_tlli_info *tlli_info;
1350
1351 printf("Test TLLI replacement:\n");
1352
1353 cfg.tlli_max_len = 0;
1354 cfg.tlli_max_age = 0;
1355 peer = gbproxy_peer_alloc(&cfg, 20);
1356 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1357
1358 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001359 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001360 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1361
1362 /* replace the old entry */
1363 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001364 gbprox_register_tlli(peer, tlli2, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001365 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1366
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001367 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001368
1369 /* verify that 5678 has survived */
1370 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1371 OSMO_ASSERT(tlli_info);
1372 OSMO_ASSERT(tlli_info->tlli == tlli2);
1373 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1374 OSMO_ASSERT(!tlli_info);
1375
1376 printf("\n");
1377
1378 gbproxy_peer_free(peer);
1379 }
1380
1381 {
1382 struct gbproxy_tlli_info *tlli_info;
1383
1384 printf("Test IMSI replacement:\n");
1385
1386 cfg.tlli_max_len = 0;
1387 cfg.tlli_max_age = 0;
1388 peer = gbproxy_peer_alloc(&cfg, 20);
1389 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1390
1391 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001392 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001393 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1394
1395 /* try to replace the old entry */
1396 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001397 gbprox_register_tlli(peer, tlli1, imsi2, ARRAY_SIZE(imsi2), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001398 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1399
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001400 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001401
1402 /* verify that 5678 has survived */
1403 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1404 OSMO_ASSERT(!tlli_info);
1405 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1406 OSMO_ASSERT(tlli_info);
1407 OSMO_ASSERT(tlli_info->tlli == tlli1);
1408
1409 printf("\n");
1410
1411 gbproxy_peer_free(peer);
1412 }
1413
1414 {
1415 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001416 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001417
1418 printf("Test TLLI expiry, max_len == 1:\n");
1419
1420 cfg.tlli_max_len = 1;
1421 cfg.tlli_max_age = 0;
1422 peer = gbproxy_peer_alloc(&cfg, 20);
1423 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1424
1425 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001426 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001427 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1428
1429 /* replace the old entry */
1430 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001431 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001432 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1433
1434 num_removed = gbprox_remove_stale_tllis(peer, time(NULL) + 2);
1435 OSMO_ASSERT(num_removed == 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001436 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1437
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001438 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001439
1440 /* verify that 5678 has survived */
1441 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1442 OSMO_ASSERT(!tlli_info);
1443 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1444 OSMO_ASSERT(tlli_info);
1445 OSMO_ASSERT(tlli_info->tlli == tlli2);
1446
1447 printf("\n");
1448
1449 gbproxy_peer_free(peer);
1450 }
1451
1452 {
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001453 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001454
1455 printf("Test TLLI expiry, max_age == 1:\n");
1456
1457 cfg.tlli_max_len = 0;
1458 cfg.tlli_max_age = 1;
1459 peer = gbproxy_peer_alloc(&cfg, 20);
1460 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1461
1462 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001463 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001464 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1465
1466 /* replace the old entry */
1467 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001468 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001469 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1470
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001471 num_removed = gbprox_remove_stale_tllis(peer, now + 2);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001472 OSMO_ASSERT(num_removed == 2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001473 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1474
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001475 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001476
1477 printf("\n");
1478
1479 gbproxy_peer_free(peer);
1480 }
1481}
1482
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001483static void test_gbproxy_imsi_matching(void)
1484{
1485 struct gbproxy_config cfg = {0};
1486 struct gbproxy_peer *peer;
1487 const char *err_msg = NULL;
1488 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
1489 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1490 const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
1491 const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
1492 const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
1493 const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
1494 const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
1495 const char *filter_re1 = ".*";
1496 const char *filter_re2 = "^1234";
1497 const char *filter_re3 = "^4321";
1498 const char *filter_re4_bad = "^12[";
1499
1500 printf("=== Test IMSI/TMSI matching ===\n\n");
1501
1502 gbproxy_init_config(&cfg);
1503 OSMO_ASSERT(cfg.check_imsi == 0);
1504
1505 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
1506 OSMO_ASSERT(cfg.check_imsi == 1);
1507
1508 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1509 OSMO_ASSERT(cfg.check_imsi == 1);
1510
1511 err_msg = NULL;
1512 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
1513 OSMO_ASSERT(err_msg != NULL);
1514 OSMO_ASSERT(cfg.check_imsi == 0);
1515
1516 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1517 OSMO_ASSERT(cfg.check_imsi == 1);
1518
1519 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, NULL, &err_msg) == 0);
1520 OSMO_ASSERT(cfg.check_imsi == 0);
1521
1522 peer = gbproxy_peer_alloc(&cfg, 20);
1523
1524 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
1525 OSMO_ASSERT(cfg.check_imsi == 1);
1526
1527 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
1528 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
1529 /* imsi3_bad contains 0xE and 0xF digits, but the conversion function
1530 * doesn't complain, so gbprox_check_imsi() doesn't return -1 in this
1531 * case. */
1532 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1533 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1534 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1535 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1536 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1537
1538 OSMO_ASSERT(gbprox_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
1539 OSMO_ASSERT(cfg.check_imsi == 1);
1540
1541 OSMO_ASSERT(gbprox_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
1542 OSMO_ASSERT(gbprox_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
1543 OSMO_ASSERT(gbprox_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
1544 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
1545 OSMO_ASSERT(gbprox_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
1546 OSMO_ASSERT(gbprox_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
1547 OSMO_ASSERT(gbprox_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
1548
1549 /* TODO: Check correct length but wrong type with is_mi_tmsi */
1550
1551 gbproxy_peer_free(peer);
1552}
1553
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001554static struct log_info_cat gprs_categories[] = {
1555 [DGPRS] = {
1556 .name = "DGPRS",
1557 .description = "GPRS Packet Service",
1558 .enabled = 1, .loglevel = LOGL_DEBUG,
1559 },
1560 [DNS] = {
1561 .name = "DNS",
1562 .description = "GPRS Network Service (NS)",
1563 .enabled = 1, .loglevel = LOGL_INFO,
1564 },
1565 [DBSSGP] = {
1566 .name = "DBSSGP",
1567 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1568 .enabled = 1, .loglevel = LOGL_DEBUG,
1569 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001570};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001571
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001572static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001573 .cat = gprs_categories,
1574 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001575};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001576
1577int main(int argc, char **argv)
1578{
1579 osmo_init_logging(&info);
1580 log_set_use_color(osmo_stderr_target, 0);
1581 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001582 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001583
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001584 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001585 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1586 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001587
1588 rate_ctr_init(NULL);
1589
1590 setlinebuf(stdout);
1591
1592 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02001593 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001594 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001595 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001596 test_gbproxy_ident_changes();
Jacob Erlbeck291f0502014-08-07 10:46:29 +02001597 test_gbproxy_imsi_matching();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001598 test_gbproxy_ra_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001599 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001600 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001601
1602 exit(EXIT_SUCCESS);
1603}