blob: 769dc675dbf09f775c275c81f31b2d2adbee54a7 [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
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200149/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Request */
150static const unsigned char bssgp_identity_req[] = {
151 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
152 0x16, 0x82, 0x02, 0x58, 0x0e, 0x89, 0x41, 0xc0,
153 0x01, 0x08, 0x15, 0x01, 0xff, 0x6c, 0xba
154};
155
156/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Identity Response */
157static const unsigned char bssgp_identity_resp[] = {
158 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
159 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
160 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x11, 0x01,
161 0xc0, 0x0d, 0x08, 0x16, 0x08, 0x11, 0x12, 0x13,
162 0x14, 0x15, 0x16, 0x17, 0x18, 0xb7, 0x1b, 0x9a
163};
164
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200165/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */
166static const unsigned char bssgp_attach_acc[88] = {
167 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
168 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
169 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
170 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
171 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
172 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
173 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
174 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01,
175 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60,
176 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05,
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +0200177 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x42, 0x67, 0x9a
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200178};
179
Jacob Erlbeck11669742014-06-06 18:47:36 +0200180/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - GMM Information */
181static const unsigned char bssgp_gmm_information[66] = {
182 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
183 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
184 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
185 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
186 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
187 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
188 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
189 0x0e, 0x88, 0x41, 0xc0, 0x09, 0x08, 0x21, 0x04,
190 0xba, 0x3d
191};
192
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200193/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */
194static const unsigned char bssgp_ra_upd_req[85] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200195 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200196 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
197 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01,
198 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33,
199 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33,
200 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48,
201 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8,
202 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02,
203 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27,
204 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02,
205 0x20, 0x00, 0x96, 0x3e, 0x97
206};
207
208/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */
209static const unsigned char bssgp_ra_upd_acc[91] = {
Jacob Erlbeck11669742014-06-06 18:47:36 +0200210 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200211 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13,
212 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02,
213 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48,
214 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8,
215 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d,
216 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
217 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0,
218 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
219 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
220 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16,
221 0xc3, 0xbf, 0xcc
222};
223
224/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */
225static const unsigned char bssgp_act_pdp_ctx_req[76] = {
226 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
227 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
228 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01,
229 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
230 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
232 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
233 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
234 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
235 0x00, 0x5a, 0xff, 0x02
236};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200237
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200238/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Request */
239static const unsigned char bssgp_detach_req[44] = {
240 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
241 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
242 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x15, 0x01,
243 0xc0, 0x19, 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4,
244 0xef, 0xe2, 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97,
245 0xcb, 0x7e, 0xe1, 0x41
246};
247
248/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Accept */
249static const unsigned char bssgp_detach_acc[67] = {
250 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
251 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
252 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
253 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
254 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
255 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
256 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
257 0x0e, 0x89, 0x41, 0xc0, 0x15, 0x08, 0x06, 0x00,
258 0xf7, 0x35, 0xf0
259};
260
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200261static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
262 struct sockaddr_in *peer, const unsigned char* data,
263 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200264
265static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
266 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
267{
268 /* GPRS Network Service, PDU type: NS_RESET,
269 */
270 unsigned char msg[12] = {
271 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
272 0x04, 0x82, 0x11, 0x22
273 };
274
275 msg[3] = cause;
276 msg[6] = nsvci / 256;
277 msg[7] = nsvci % 256;
278 msg[10] = nsei / 256;
279 msg[11] = nsei % 256;
280
281 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
282}
283
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200284static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
285 uint16_t nsvci, uint16_t nsei)
286{
287 /* GPRS Network Service, PDU type: NS_RESET_ACK,
288 */
289 unsigned char msg[9] = {
290 0x03, 0x01, 0x82, 0x11, 0x22,
291 0x04, 0x82, 0x11, 0x22
292 };
293
294 msg[3] = nsvci / 256;
295 msg[4] = nsvci % 256;
296 msg[7] = nsei / 256;
297 msg[8] = nsei % 256;
298
299 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
300}
301
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200302static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
303{
304 /* GPRS Network Service, PDU type: NS_ALIVE */
305 unsigned char msg[1] = {
306 0x0a
307 };
308
309 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
310}
311
312static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
313{
314 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
315 unsigned char msg[1] = {
316 0x0b
317 };
318
319 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
320}
321
322static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
323{
324 /* GPRS Network Service, PDU type: NS_UNBLOCK */
325 unsigned char msg[1] = {
326 0x06
327 };
328
329 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
330}
331
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200332static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
333{
334 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
335 unsigned char msg[1] = {
336 0x07
337 };
338
339 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
340}
341
342static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
343 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200344 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
345{
346 /* GPRS Network Service, PDU type: NS_UNITDATA */
347 unsigned char msg[4096] = {
348 0x00, 0x00, 0x00, 0x00
349 };
350
351 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
352
353 msg[2] = nsbvci / 256;
354 msg[3] = nsbvci % 256;
355 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
356
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200357 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200358}
359
360static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
361 uint16_t bvci)
362{
363 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
364 * BSSGP RESET */
Jacob Erlbeckda4b4922014-08-06 12:38:10 +0200365 unsigned char msg[18] = {
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200366 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200367 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
368 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200369 };
370
371 msg[3] = bvci / 256;
372 msg[4] = bvci % 256;
373
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200374 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
375}
376
377static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
378 struct sockaddr_in *src_addr, uint16_t bvci)
379{
380 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
381 * BSSGP RESET_ACK */
382 static unsigned char msg[5] = {
383 0x23, 0x04, 0x82, 0x00,
384 0x00
385 };
386
387 msg[3] = bvci / 256;
388 msg[4] = bvci % 256;
389
390 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200391}
392
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200393static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
394 struct sockaddr_in *src_addr,
395 struct gprs_ra_id *raid)
396{
397 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
398 unsigned char msg[15] = {
399 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
400 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
401 };
402
403 gsm48_construct_ra(msg + 9, raid);
404
405 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
406}
407
408static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
409 struct sockaddr_in *src_addr,
410 struct gprs_ra_id *raid)
411{
412 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
413 unsigned char msg[18] = {
414 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
415 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
416 0x81, 0x01
417 };
418
419 gsm48_construct_ra(msg + 9, raid);
420
421 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
422}
423
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200424static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
425 uint16_t nsvci, uint16_t nsei)
426{
427 printf("Setup NS-VC: remote 0x%08x:%d, "
428 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
429 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
430 nsvci, nsvci, nsei, nsei);
431
432 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
433 send_ns_alive(nsi, src_addr);
434 send_ns_unblock(nsi, src_addr);
435 send_ns_alive_ack(nsi, src_addr);
436}
437
438static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
439 uint16_t bvci)
440{
441 printf("Setup BSSGP: remote 0x%08x:%d, "
442 "BVCI 0x%04x(%d)\n\n",
443 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
444 bvci, bvci);
445
446 send_bssgp_reset(nsi, src_addr, bvci);
447}
448
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200449static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
450{
451 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
452 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
453 send_ns_alive_ack(nsi, sgsn_peer);
454 send_ns_unblock_ack(nsi, sgsn_peer);
455 send_ns_alive(nsi, sgsn_peer);
456}
457
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200458static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
459{
460 sgsn_peer->sin_family = AF_INET;
461 sgsn_peer->sin_port = htons(32000);
462 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
463}
464
465static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
466{
467 size_t i;
468
469 for (i = 0; i < size; ++i) {
470 bss_peers[i].sin_family = AF_INET;
471 bss_peers[i].sin_port = htons((i + 1) * 1111);
472 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
473 }
474}
475
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200476int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
477 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
478
479/* override */
480int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
481 struct msgb *msg, uint16_t bvci)
482{
483 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
484 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200485 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200486
487 switch (event) {
488 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200489 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200490 default:
491 break;
492 }
493 return 0;
494}
495
496/* override */
497ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
498 const struct sockaddr *dest_addr, socklen_t addrlen)
499{
500 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
501 const struct sockaddr *, socklen_t);
502 static sendto_t real_sendto = NULL;
503 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200504 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200505
506 if (!real_sendto)
507 real_sendto = dlsym(RTLD_NEXT, "sendto");
508
509 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200510 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
511 dest_host, dest_port,
512 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200513 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200514 printf("MESSAGE to SGSN 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
518 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
519
520 return len;
521}
522
523/* override */
524int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
525{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200526 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
527 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200528 uint16_t bvci = msgb_bvci(msg);
529 uint16_t nsei = msgb_nsei(msg);
530
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200531 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200532
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200533 if (!real_gprs_ns_sendmsg)
534 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
535
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200536 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200537 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
538 "msg length %d (%s)\n",
539 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200540 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200541 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
542 "msg length %d (%s)\n",
543 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200544
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200545 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200546}
547
548static void dump_rate_ctr_group(FILE *stream, const char *prefix,
549 struct rate_ctr_group *ctrg)
550{
551 unsigned int i;
552
553 for (i = 0; i < ctrg->desc->num_ctr; i++) {
554 struct rate_ctr *ctr = &ctrg->ctr[i];
555 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
556 fprintf(stream, " %s%s: %llu%s",
557 prefix, ctrg->desc->ctr_desc[i].description,
558 (long long)ctr->current,
559 "\n");
560 };
561}
562
563/* Signal handler for signals from NS layer */
564static int test_signal(unsigned int subsys, unsigned int signal,
565 void *handler_data, void *signal_data)
566{
567 struct ns_signal_data *nssd = signal_data;
568 int rc;
569
570 if (subsys != SS_L_NS)
571 return 0;
572
573 switch (signal) {
574 case S_NS_RESET:
575 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
576 nssd->nsvc->nsvci,
577 gprs_ns_ll_str(nssd->nsvc));
578 break;
579
580 case S_NS_ALIVE_EXP:
581 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
582 nssd->nsvc->nsvci,
583 gprs_ns_ll_str(nssd->nsvc));
584 break;
585
586 case S_NS_BLOCK:
587 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
588 nssd->nsvc->nsvci,
589 gprs_ns_ll_str(nssd->nsvc));
590 break;
591
592 case S_NS_UNBLOCK:
593 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
594 nssd->nsvc->nsvci,
595 gprs_ns_ll_str(nssd->nsvc));
596 break;
597
598 case S_NS_REPLACED:
599 printf("==> got signal NS_REPLACED: 0x%04x/%s",
600 nssd->nsvc->nsvci,
601 gprs_ns_ll_str(nssd->nsvc));
602 printf(" -> 0x%04x/%s\n",
603 nssd->old_nsvc->nsvci,
604 gprs_ns_ll_str(nssd->old_nsvc));
605 break;
606
607 default:
608 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
609 nssd->nsvc->nsvci,
610 gprs_ns_ll_str(nssd->nsvc));
611 break;
612 }
613 printf("\n");
614 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
615 return rc;
616}
617
618static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
619{
620 struct msgb *msg;
621 int ret;
622 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
623 fprintf(stderr, "message too long: %d\n", data_len);
624 return -1;
625 }
626
627 msg = gprs_ns_msgb_alloc();
628 memmove(msg->data, data, data_len);
629 msg->l2h = msg->data;
630 msgb_put(msg, data_len);
631
632 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
633 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
634 osmo_hexdump(data, data_len));
635
636 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
637
638 printf("result (%s) = %d\n\n", text, ret);
639
640 msgb_free(msg);
641
642 return ret;
643}
644
645static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
646{
647 struct gprs_nsvc *nsvc;
648
649 printf("Current NS-VCIs:\n");
650 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
651 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200652 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200653 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200654 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
655 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
656 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200657 );
658 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
659 }
660 printf("\n");
661}
662
663static void test_gbproxy()
664{
665 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
666 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200667 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200668
669 bssgp_nsi = nsi;
670 gbcfg.nsi = bssgp_nsi;
671 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
672
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200673 configure_sgsn_peer(&sgsn_peer);
674 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200675
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200676 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200677 printf("--- Initialise SGSN ---\n\n");
678
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200679 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200680 gprs_dump_nsi(nsi);
681
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200682 printf("--- Initialise BSS 1 ---\n\n");
683
684 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
685 setup_bssgp(nsi, &bss_peer[0], 0x1002);
686 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200687 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200688
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200689 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
690
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200691 printf("--- Initialise BSS 2 ---\n\n");
692
693 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
694 setup_bssgp(nsi, &bss_peer[1], 0x2002);
695 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200696 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200697
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200698 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
699
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200700 printf("--- Move BSS 1 to new port ---\n\n");
701
702 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
703 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200704 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200705
706 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
707
708 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
709 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200710 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200711
712 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
713
714 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
715 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200716 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200717
718 printf("--- Move BSS 2 to new port ---\n\n");
719
720 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
721 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200722 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200723
724 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
725
726 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
727 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200728 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200729
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200730 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
731
732 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
733 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200734 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200735
736 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
737
738 setup_bssgp(nsi, &bss_peer[0], 0x1012);
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, 0x1012);
743
744 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
745
746 setup_bssgp(nsi, &bss_peer[0], 0x1002);
747 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200748 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200749
750 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
751
752 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
753
754 setup_bssgp(nsi, &bss_peer[0], 0x1002);
755 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200756 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200757
758 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
759
760 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
761
762 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
763
764 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
765
766 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
767
768 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
769
770 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
771
772 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
773
774 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
775
776 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
777
778 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
779
780 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
781
782 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
783
784 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
785
786 setup_bssgp(nsi, &bss_peer[2], 0x1002);
787 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200788 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200789
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200790 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200791
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200792 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
793
794 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
795
796 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
797
798 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
799
800 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
801
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200802 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
803
804 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
805
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200806 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200807
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200808 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200809 gprs_ns_destroy(nsi);
810 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200811}
812
813static void test_gbproxy_ident_changes()
814{
815 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
816 struct sockaddr_in bss_peer[1] = {{0},};
817 struct sockaddr_in sgsn_peer= {0};
818 uint16_t nsei[2] = {0x1000, 0x2000};
819 uint16_t nsvci[2] = {0x1001, 0x2001};
820 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
821
822 bssgp_nsi = nsi;
823 gbcfg.nsi = bssgp_nsi;
824 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
825
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200826 configure_sgsn_peer(&sgsn_peer);
827 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200828
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200829 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200830 printf("--- Initialise SGSN ---\n\n");
831
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200832 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200833 gprs_dump_nsi(nsi);
834
835 printf("--- Initialise BSS 1 ---\n\n");
836
837 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
838 gprs_dump_nsi(nsi);
839
840 printf("--- Setup BVCI 1 ---\n\n");
841
842 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
843 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200844 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200845
846 printf("--- Setup BVCI 2 ---\n\n");
847
848 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
849 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200850 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200851
852 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
853
854 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
855 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
856
857 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
858
859 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
860 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
861
862 printf("--- Change NSEI ---\n\n");
863
864 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
865 gprs_dump_nsi(nsi);
866
867 printf("--- Setup BVCI 1 ---\n\n");
868
869 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
870 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200871 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200872
873 printf("--- Setup BVCI 3 ---\n\n");
874
875 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
876 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200877 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200878
879 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
880
881 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
882 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
883
884 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
885 " (should fail) ---\n\n");
886
887 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200888 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200889 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 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("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
893
894 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
895 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
896
897 printf("--- Change NSVCI ---\n\n");
898
899 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
900 gprs_dump_nsi(nsi);
901
902 printf("--- Setup BVCI 1 ---\n\n");
903
904 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
905 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200906 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200907
908 printf("--- Setup BVCI 4 ---\n\n");
909
910 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
911 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200912 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200913
914 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
915
916 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
917 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
918
919 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
920 " (should fail) ---\n\n");
921
922 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200923 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200924 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200925 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200926
927 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
928
929 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
930 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
931
932 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
933
934 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
935 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
936
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200937 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200938 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200939
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200940 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +0200941 gprs_ns_destroy(nsi);
942 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200943}
944
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200945static void test_gbproxy_ra_patching()
946{
947 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
948 struct sockaddr_in bss_peer[1] = {{0},};
949 struct sockaddr_in sgsn_peer= {0};
950 struct gprs_ra_id rai_bss =
951 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
952 struct gprs_ra_id rai_sgsn =
953 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
954 struct gprs_ra_id rai_unknown =
955 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200956 const char *err_msg = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200957
958 bssgp_nsi = nsi;
959 gbcfg.nsi = bssgp_nsi;
960 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200961 gbcfg.core_mcc = 123;
962 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200963 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200964 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200965
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200966 configure_sgsn_peer(&sgsn_peer);
967 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200968
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200969 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Holger Hans Peter Freyther3fa26442014-08-04 16:27:11 +0200970 if (gbprox_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200971 fprintf(stderr, "Failed to compile RE '%s': %s\n",
972 gbcfg.match_re, err_msg);
973 exit(1);
974 }
975
976
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200977 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200978 printf("--- Initialise SGSN ---\n\n");
979
980 connect_sgsn(nsi, &sgsn_peer);
981 gprs_dump_nsi(nsi);
982
983 printf("--- Initialise BSS 1 ---\n\n");
984
985 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
986 setup_bssgp(nsi, &bss_peer[0], 0x1002);
987 gprs_dump_nsi(nsi);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200988 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200989
990 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
991
992 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
993 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
994
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200995 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +0200996 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200997
998 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
999
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001000 send_ns_unitdata(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001001 bssgp_attach_req, sizeof(bssgp_attach_req));
1002
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001003 send_ns_unitdata(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1004 bssgp_identity_req, sizeof(bssgp_identity_req));
1005
1006 send_ns_unitdata(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1007 bssgp_identity_resp, sizeof(bssgp_identity_resp));
1008
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001009 send_ns_unitdata(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001010 bssgp_attach_acc, sizeof(bssgp_attach_acc));
1011
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001012 /* Replace APN (1) */
1013 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
1014 &bss_peer[0], 0x1002,
1015 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001016
Jacob Erlbeck11669742014-06-06 18:47:36 +02001017 send_ns_unitdata(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1018 bssgp_gmm_information, sizeof(bssgp_gmm_information));
1019
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001020 /* Replace APN (2) */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001021 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
1022 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001023 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1024
Jacob Erlbeck73685282014-05-23 20:48:07 +02001025 gbcfg.core_apn[0] = 0;
1026 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001027
1028 /* Remove APN */
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001029 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1030 &bss_peer[0], 0x1002,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001031 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1032
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001033 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001034
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001035 /* Detach */
1036 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1037 bssgp_detach_req, sizeof(bssgp_detach_req));
1038
1039 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1040 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1041
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001042 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001043
1044 printf("--- RA update ---\n\n");
1045
1046 send_ns_unitdata(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1047 bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req));
1048
1049 send_ns_unitdata(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1050 bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc));
1051
1052 /* Remove APN */
1053 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
1054 &bss_peer[0], 0x1002,
1055 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1056
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001057 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001058
1059 /* Detach */
1060 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1061 bssgp_detach_req, sizeof(bssgp_detach_req));
1062
1063 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1064 bssgp_detach_acc, sizeof(bssgp_detach_acc));
1065
1066
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001067 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001068 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001069
1070 printf("--- Bad cases ---\n\n");
1071
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001072 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001073 send_ns_unitdata(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1074 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
1075
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001076 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001077 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1078
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001079 dump_global(stdout, 0);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001080 dump_peers(stdout, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001081
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001082 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001083 gprs_ns_destroy(nsi);
1084 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001085}
1086
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001087/* TODO: Move tlv testing to libosmocore */
1088int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1089int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1090 uint8_t **value);
1091int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1092 size_t *value_len);
1093int lv_shift(uint8_t **data, size_t *data_len,
1094 uint8_t **value, size_t *value_len);
1095
1096static void check_tlv_match(uint8_t **data, size_t *data_len,
1097 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1098{
1099 uint8_t *value;
1100 size_t value_len;
1101 int rc;
1102
1103 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1104 OSMO_ASSERT(rc == 0);
1105
1106 rc = tlv_match(data, data_len, tag, &value, &value_len);
1107 OSMO_ASSERT(rc == value_len + 2);
1108 OSMO_ASSERT(value_len == exp_len);
1109 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1110}
1111
1112static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1113 uint8_t tag, size_t len, const uint8_t *exp_val)
1114{
1115 uint8_t *value;
1116 int rc;
1117
1118 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1119 OSMO_ASSERT(rc == 0);
1120
1121 rc = tv_fixed_match(data, data_len, tag, len, &value);
1122 OSMO_ASSERT(rc == len + 1);
1123 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1124}
1125
1126static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1127 size_t len, const uint8_t *exp_val)
1128{
1129 uint8_t *value;
1130 int rc;
1131
1132 rc = v_fixed_shift(data, data_len, len, &value);
1133 OSMO_ASSERT(rc == len);
1134 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1135}
1136
1137static void check_lv_shift(uint8_t **data, size_t *data_len,
1138 size_t exp_len, const uint8_t *exp_val)
1139{
1140 uint8_t *value;
1141 size_t value_len;
1142 int rc;
1143
1144 rc = lv_shift(data, data_len, &value, &value_len);
1145 OSMO_ASSERT(rc == value_len + 1);
1146 OSMO_ASSERT(value_len == exp_len);
1147 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1148}
1149
1150static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1151 const uint8_t *test_data)
1152{
1153 uint8_t buf[300] = {0};
1154
1155 uint8_t *unchanged_ptr = buf - 1;
1156 size_t unchanged_len = 0xdead;
1157 size_t tmp_data_len = data_len;
1158 uint8_t *value = unchanged_ptr;
1159 size_t value_len = unchanged_len;
1160 uint8_t *data = buf;
1161
1162 OSMO_ASSERT(data_len <= sizeof(buf));
1163
1164 tlv_put(data, tag, len, test_data);
1165 if (data_len < len + 2) {
1166 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1167 tag, &value, &value_len));
1168 OSMO_ASSERT(tmp_data_len == 0);
1169 OSMO_ASSERT(data == buf + data_len);
1170 OSMO_ASSERT(value == unchanged_ptr);
1171 OSMO_ASSERT(value_len == unchanged_len);
1172 } else {
1173 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1174 tag, &value, &value_len));
1175 OSMO_ASSERT(value != unchanged_ptr);
1176 OSMO_ASSERT(value_len != unchanged_len);
1177 }
1178}
1179
1180static void check_tv_fixed_match_data_len(size_t data_len,
1181 uint8_t tag, size_t len,
1182 const uint8_t *test_data)
1183{
1184 uint8_t buf[300] = {0};
1185
1186 uint8_t *unchanged_ptr = buf - 1;
1187 size_t tmp_data_len = data_len;
1188 uint8_t *value = unchanged_ptr;
1189 uint8_t *data = buf;
1190
1191 OSMO_ASSERT(data_len <= sizeof(buf));
1192
1193 tv_fixed_put(data, tag, len, test_data);
1194
1195 if (data_len < len + 1) {
1196 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1197 tag, len, &value));
1198 OSMO_ASSERT(tmp_data_len == 0);
1199 OSMO_ASSERT(data == buf + data_len);
1200 OSMO_ASSERT(value == unchanged_ptr);
1201 } else {
1202 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1203 tag, len, &value));
1204 OSMO_ASSERT(value != unchanged_ptr);
1205 }
1206}
1207
1208static void check_v_fixed_shift_data_len(size_t data_len,
1209 size_t len, const uint8_t *test_data)
1210{
1211 uint8_t buf[300] = {0};
1212
1213 uint8_t *unchanged_ptr = buf - 1;
1214 size_t tmp_data_len = data_len;
1215 uint8_t *value = unchanged_ptr;
1216 uint8_t *data = buf;
1217
1218 OSMO_ASSERT(data_len <= sizeof(buf));
1219
1220 memcpy(data, test_data, len);
1221
1222 if (data_len < len) {
1223 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1224 len, &value));
1225 OSMO_ASSERT(tmp_data_len == 0);
1226 OSMO_ASSERT(data == buf + data_len);
1227 OSMO_ASSERT(value == unchanged_ptr);
1228 } else {
1229 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1230 len, &value));
1231 OSMO_ASSERT(value != unchanged_ptr);
1232 }
1233}
1234
1235static void check_lv_shift_data_len(size_t data_len,
1236 size_t len, const uint8_t *test_data)
1237{
1238 uint8_t buf[300] = {0};
1239
1240 uint8_t *unchanged_ptr = buf - 1;
1241 size_t unchanged_len = 0xdead;
1242 size_t tmp_data_len = data_len;
1243 uint8_t *value = unchanged_ptr;
1244 size_t value_len = unchanged_len;
1245 uint8_t *data = buf;
1246
1247 lv_put(data, len, test_data);
1248 if (data_len < len + 1) {
1249 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1250 &value, &value_len));
1251 OSMO_ASSERT(tmp_data_len == 0);
1252 OSMO_ASSERT(data == buf + data_len);
1253 OSMO_ASSERT(value == unchanged_ptr);
1254 OSMO_ASSERT(value_len == unchanged_len);
1255 } else {
1256 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1257 &value, &value_len));
1258 OSMO_ASSERT(value != unchanged_ptr);
1259 OSMO_ASSERT(value_len != unchanged_len);
1260 }
1261}
1262
1263static void test_tlv_shift_functions()
1264{
1265 uint8_t test_data[1024];
1266 uint8_t buf[1024];
1267 uint8_t *data_end;
1268 int i, len;
1269 uint8_t *data;
1270 size_t data_len;
1271 const uint8_t tag = 0x1a;
1272
1273 printf("Test shift functions\n");
1274
1275 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1276 test_data[i] = (uint8_t)i;
1277
1278 for (len = 0; len < 256; len++) {
1279 const int iterations = sizeof(buf) / (len + 2) / 4;
1280
1281 memset(buf, 0xee, sizeof(buf));
1282 data_end = data = buf;
1283
1284 for (i = 0; i < iterations; i++) {
1285 data_end = tlv_put(data_end, tag, len, test_data);
1286 data_end = tv_fixed_put(data_end, tag, len, test_data);
1287 /* v_fixed_put */
1288 memcpy(data_end, test_data, len);
1289 data_end += len;
1290 data_end = lv_put(data_end, len, test_data);
1291 }
1292
1293 data_len = data_end - data;
1294 OSMO_ASSERT(data_len <= sizeof(buf));
1295
1296 for (i = 0; i < iterations; i++) {
1297 check_tlv_match(&data, &data_len, tag, len, test_data);
1298 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1299 check_v_fixed_shift(&data, &data_len, len, test_data);
1300 check_lv_shift(&data, &data_len, len, test_data);
1301 }
1302
1303 OSMO_ASSERT(data == data_end);
1304
1305 /* Test at end of data */
1306
1307 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1308 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1309 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1310 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1311
1312 /* Test invalid data_len */
1313 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1314 check_tlv_match_data_len(data_len, tag, len, test_data);
1315 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1316 check_v_fixed_shift_data_len(data_len, len, test_data);
1317 check_lv_shift_data_len(data_len, len, test_data);
1318 }
1319 }
1320}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001321
1322static void test_gbproxy_tlli_expire(void)
1323{
1324 struct gbproxy_config cfg = {0};
1325 struct gbproxy_peer *peer;
1326 const char *err_msg = NULL;
1327 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1328 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
1329 const uint32_t tlli1 = 1234 | 0xc0000000;
1330 const uint32_t tlli2 = 5678 | 0xc0000000;
1331 const char *filter_re = ".*";
1332
1333 printf("Test TLLI info expiry\n\n");
1334
1335 gbproxy_init_config(&cfg);
1336
1337 if (gbprox_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
1338 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1339 err_msg);
1340 OSMO_ASSERT(err_msg == NULL);
1341 }
1342
1343 {
1344 struct gbproxy_tlli_info *tlli_info;
1345
1346 printf("Test TLLI replacement:\n");
1347
1348 cfg.tlli_max_len = 0;
1349 cfg.tlli_max_age = 0;
1350 peer = gbproxy_peer_alloc(&cfg, 20);
1351 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1352
1353 printf(" Add TLLI 1, IMSI 1\n");
1354 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1355 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1356
1357 /* replace the old entry */
1358 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
1359 gbprox_register_tlli(peer, tlli2, imsi1, ARRAY_SIZE(imsi1));
1360 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1361
1362 dump_peers(stdout, 2, &cfg);
1363
1364 /* verify that 5678 has survived */
1365 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1366 OSMO_ASSERT(tlli_info);
1367 OSMO_ASSERT(tlli_info->tlli == tlli2);
1368 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1369 OSMO_ASSERT(!tlli_info);
1370
1371 printf("\n");
1372
1373 gbproxy_peer_free(peer);
1374 }
1375
1376 {
1377 struct gbproxy_tlli_info *tlli_info;
1378
1379 printf("Test IMSI replacement:\n");
1380
1381 cfg.tlli_max_len = 0;
1382 cfg.tlli_max_age = 0;
1383 peer = gbproxy_peer_alloc(&cfg, 20);
1384 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1385
1386 printf(" Add TLLI 1, IMSI 1\n");
1387 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1388 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1389
1390 /* try to replace the old entry */
1391 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
1392 gbprox_register_tlli(peer, tlli1, imsi2, ARRAY_SIZE(imsi2));
1393 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1394
1395 dump_peers(stdout, 2, &cfg);
1396
1397 /* verify that 5678 has survived */
1398 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1399 OSMO_ASSERT(!tlli_info);
1400 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1401 OSMO_ASSERT(tlli_info);
1402 OSMO_ASSERT(tlli_info->tlli == tlli1);
1403
1404 printf("\n");
1405
1406 gbproxy_peer_free(peer);
1407 }
1408
1409 {
1410 struct gbproxy_tlli_info *tlli_info;
1411
1412 printf("Test TLLI expiry, max_len == 1:\n");
1413
1414 cfg.tlli_max_len = 1;
1415 cfg.tlli_max_age = 0;
1416 peer = gbproxy_peer_alloc(&cfg, 20);
1417 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1418
1419 printf(" Add TLLI 1, IMSI 1\n");
1420 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1421 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1422
1423 /* replace the old entry */
1424 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
1425 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2));
1426 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1427
1428 dump_peers(stdout, 2, &cfg);
1429
1430 /* verify that 5678 has survived */
1431 tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
1432 OSMO_ASSERT(!tlli_info);
1433 tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
1434 OSMO_ASSERT(tlli_info);
1435 OSMO_ASSERT(tlli_info->tlli == tlli2);
1436
1437 printf("\n");
1438
1439 gbproxy_peer_free(peer);
1440 }
1441
1442 {
1443 int ret;
1444
1445 printf("Test TLLI expiry, max_age == 1:\n");
1446
1447 cfg.tlli_max_len = 0;
1448 cfg.tlli_max_age = 1;
1449 peer = gbproxy_peer_alloc(&cfg, 20);
1450 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1451
1452 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
1453 gbprox_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1));
1454 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1455
1456 /* replace the old entry */
1457 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
1458 gbprox_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2));
1459 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1460
1461 ret = gbprox_remove_stale_tllis(peer, time(NULL) + 2);
1462 OSMO_ASSERT(ret == 2);
1463 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1464
1465 dump_peers(stdout, 2, &cfg);
1466
1467 printf("\n");
1468
1469 gbproxy_peer_free(peer);
1470 }
1471}
1472
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001473static struct log_info_cat gprs_categories[] = {
1474 [DGPRS] = {
1475 .name = "DGPRS",
1476 .description = "GPRS Packet Service",
1477 .enabled = 1, .loglevel = LOGL_DEBUG,
1478 },
1479 [DNS] = {
1480 .name = "DNS",
1481 .description = "GPRS Network Service (NS)",
1482 .enabled = 1, .loglevel = LOGL_INFO,
1483 },
1484 [DBSSGP] = {
1485 .name = "DBSSGP",
1486 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1487 .enabled = 1, .loglevel = LOGL_DEBUG,
1488 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001489};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001490
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001491static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001492 .cat = gprs_categories,
1493 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02001494};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001495
1496int main(int argc, char **argv)
1497{
1498 osmo_init_logging(&info);
1499 log_set_use_color(osmo_stderr_target, 0);
1500 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001501 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001502
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001503 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02001504 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1505 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001506
1507 rate_ctr_init(NULL);
1508
1509 setlinebuf(stdout);
1510
1511 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02001512 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001513 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001514 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001515 test_gbproxy_ident_changes();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001516 test_gbproxy_ra_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001517 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001518 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001519
1520 exit(EXIT_SUCCESS);
1521}