blob: d5675d825abcf3bae08057b239aebf590d13333e [file] [log] [blame]
Jacob Erlbeck76fa57a2013-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>
16#include <sys/types.h>
17#include <sys/socket.h>
18
19#include <osmocom/core/msgb.h>
20#include <osmocom/core/application.h>
21#include <osmocom/core/utils.h>
22#include <osmocom/core/logging.h>
23#include <osmocom/core/talloc.h>
24#include <osmocom/core/signal.h>
25#include <osmocom/core/rate_ctr.h>
Jacob Erlbeck077abce2014-07-01 12:41:13 +020026#include <osmocom/gsm/tlv.h>
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +020027#include <osmocom/gprs/gprs_msgb.h>
28#include <osmocom/gprs/gprs_ns.h>
29#include <osmocom/gprs/gprs_bssgp.h>
30
31#include <openbsc/gb_proxy.h>
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +020032#include <openbsc/debug.h>
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +020033
34#define REMOTE_BSS_ADDR 0x01020304
35#define REMOTE_SGSN_ADDR 0x05060708
36
Jacob Erlbeck45017722013-10-18 13:04:47 +020037#define SGSN_NSEI 0x0100
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +020038
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +020039struct gbproxy_config gbcfg = {0};
40
41/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Request */
42static const unsigned char bssgp_attach_req[75] = {
43 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
44 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
45 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x34, 0x01,
46 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21,
47 0x08, 0x02, 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79,
48 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19, 0x18,
49 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60,
50 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80,
51 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
52 0x16, 0x6d, 0x01
53};
54
55/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */
56static const unsigned char bssgp_attach_acc[88] = {
57 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
58 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
59 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
60 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
61 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
62 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
63 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
64 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01,
65 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60,
66 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05,
Jacob Erlbeck386621c2014-06-27 11:55:04 +020067 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x42, 0x67, 0x9a
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +020068};
69
Jacob Erlbeckab7366f2014-06-06 18:47:36 +020070/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - GMM Information */
71static const unsigned char bssgp_gmm_information[66] = {
72 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
73 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
74 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
75 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
76 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
77 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
78 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
79 0x0e, 0x88, 0x41, 0xc0, 0x09, 0x08, 0x21, 0x04,
80 0xba, 0x3d
81};
82
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +020083/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */
84static const unsigned char bssgp_ra_upd_req[85] = {
Jacob Erlbeckab7366f2014-06-06 18:47:36 +020085 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +020086 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
87 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01,
88 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33,
89 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33,
90 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48,
91 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8,
92 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02,
93 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27,
94 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02,
95 0x20, 0x00, 0x96, 0x3e, 0x97
96};
97
98/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */
99static const unsigned char bssgp_ra_upd_acc[91] = {
Jacob Erlbeckab7366f2014-06-06 18:47:36 +0200100 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200101 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13,
102 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02,
103 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48,
104 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8,
105 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d,
106 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
107 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0,
108 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
109 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
110 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16,
111 0xc3, 0xbf, 0xcc
112};
113
114/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */
115static const unsigned char bssgp_act_pdp_ctx_req[76] = {
116 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
117 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
118 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01,
119 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
120 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
122 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
123 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
124 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
125 0x00, 0x5a, 0xff, 0x02
126};
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200127
Jacob Erlbeckbf6020f2014-06-19 10:23:50 +0200128/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Request */
129static const unsigned char bssgp_detach_req[44] = {
130 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04,
131 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
132 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x15, 0x01,
133 0xc0, 0x19, 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4,
134 0xef, 0xe2, 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97,
135 0xcb, 0x7e, 0xe1, 0x41
136};
137
138/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Detach Accept */
139static const unsigned char bssgp_detach_acc[67] = {
140 0x00, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x50, 0x20,
141 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3,
142 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80,
143 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba,
144 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a,
145 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13,
146 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00,
147 0x0e, 0x89, 0x41, 0xc0, 0x15, 0x08, 0x06, 0x00,
148 0xf7, 0x35, 0xf0
149};
150
Jacob Erlbeck45017722013-10-18 13:04:47 +0200151static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
152 struct sockaddr_in *peer, const unsigned char* data,
153 size_t data_len);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200154
155static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
156 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
157{
158 /* GPRS Network Service, PDU type: NS_RESET,
159 */
160 unsigned char msg[12] = {
161 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
162 0x04, 0x82, 0x11, 0x22
163 };
164
165 msg[3] = cause;
166 msg[6] = nsvci / 256;
167 msg[7] = nsvci % 256;
168 msg[10] = nsei / 256;
169 msg[11] = nsei % 256;
170
171 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
172}
173
Jacob Erlbeck45017722013-10-18 13:04:47 +0200174static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
175 uint16_t nsvci, uint16_t nsei)
176{
177 /* GPRS Network Service, PDU type: NS_RESET_ACK,
178 */
179 unsigned char msg[9] = {
180 0x03, 0x01, 0x82, 0x11, 0x22,
181 0x04, 0x82, 0x11, 0x22
182 };
183
184 msg[3] = nsvci / 256;
185 msg[4] = nsvci % 256;
186 msg[7] = nsei / 256;
187 msg[8] = nsei % 256;
188
189 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
190}
191
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200192static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
193{
194 /* GPRS Network Service, PDU type: NS_ALIVE */
195 unsigned char msg[1] = {
196 0x0a
197 };
198
199 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
200}
201
202static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
203{
204 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
205 unsigned char msg[1] = {
206 0x0b
207 };
208
209 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
210}
211
212static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
213{
214 /* GPRS Network Service, PDU type: NS_UNBLOCK */
215 unsigned char msg[1] = {
216 0x06
217 };
218
219 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
220}
221
Jacob Erlbeck45017722013-10-18 13:04:47 +0200222static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
223{
224 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
225 unsigned char msg[1] = {
226 0x07
227 };
228
229 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
230}
231
232static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
233 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200234 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
235{
236 /* GPRS Network Service, PDU type: NS_UNITDATA */
237 unsigned char msg[4096] = {
238 0x00, 0x00, 0x00, 0x00
239 };
240
241 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
242
243 msg[2] = nsbvci / 256;
244 msg[3] = nsbvci % 256;
245 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
246
Jacob Erlbeck45017722013-10-18 13:04:47 +0200247 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200248}
249
250static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
251 uint16_t bvci)
252{
253 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
254 * BSSGP RESET */
255 unsigned char msg[22] = {
256 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeck3f086322014-06-02 10:48:59 +0200257 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
258 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200259 };
260
261 msg[3] = bvci / 256;
262 msg[4] = bvci % 256;
263
Jacob Erlbeck45017722013-10-18 13:04:47 +0200264 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
265}
266
267static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
268 struct sockaddr_in *src_addr, uint16_t bvci)
269{
270 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
271 * BSSGP RESET_ACK */
272 static unsigned char msg[5] = {
273 0x23, 0x04, 0x82, 0x00,
274 0x00
275 };
276
277 msg[3] = bvci / 256;
278 msg[4] = bvci % 256;
279
280 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200281}
282
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200283static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
284 struct sockaddr_in *src_addr,
285 struct gprs_ra_id *raid)
286{
287 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
288 unsigned char msg[15] = {
289 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
290 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
291 };
292
293 gsm48_construct_ra(msg + 9, raid);
294
295 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
296}
297
298static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
299 struct sockaddr_in *src_addr,
300 struct gprs_ra_id *raid)
301{
302 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
303 unsigned char msg[18] = {
304 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
305 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
306 0x81, 0x01
307 };
308
309 gsm48_construct_ra(msg + 9, raid);
310
311 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
312}
313
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200314static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
315 uint16_t nsvci, uint16_t nsei)
316{
317 printf("Setup NS-VC: remote 0x%08x:%d, "
318 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
319 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
320 nsvci, nsvci, nsei, nsei);
321
322 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
323 send_ns_alive(nsi, src_addr);
324 send_ns_unblock(nsi, src_addr);
325 send_ns_alive_ack(nsi, src_addr);
326}
327
328static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
329 uint16_t bvci)
330{
331 printf("Setup BSSGP: remote 0x%08x:%d, "
332 "BVCI 0x%04x(%d)\n\n",
333 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
334 bvci, bvci);
335
336 send_bssgp_reset(nsi, src_addr, bvci);
337}
338
Jacob Erlbeck738b1c82014-07-07 10:46:00 +0200339static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
340{
341 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
342 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
343 send_ns_alive_ack(nsi, sgsn_peer);
344 send_ns_unblock_ack(nsi, sgsn_peer);
345 send_ns_alive(nsi, sgsn_peer);
346}
347
Holger Hans Peter Freyther731097d2014-07-07 14:19:10 +0200348static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
349{
350 sgsn_peer->sin_family = AF_INET;
351 sgsn_peer->sin_port = htons(32000);
352 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
353}
354
355static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
356{
357 size_t i;
358
359 for (i = 0; i < size; ++i) {
360 bss_peers[i].sin_family = AF_INET;
361 bss_peers[i].sin_port = htons((i + 1) * 1111);
362 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
363 }
364}
365
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200366int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
367 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
368
369/* override */
370int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
371 struct msgb *msg, uint16_t bvci)
372{
373 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
374 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200375 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200376
377 switch (event) {
378 case GPRS_NS_EVT_UNIT_DATA:
Jacob Erlbecke48c3472013-10-15 12:00:27 +0200379 return gbprox_rcvmsg(msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200380 default:
381 break;
382 }
383 return 0;
384}
385
386/* override */
387ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
388 const struct sockaddr *dest_addr, socklen_t addrlen)
389{
390 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
391 const struct sockaddr *, socklen_t);
392 static sendto_t real_sendto = NULL;
393 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200394 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200395
396 if (!real_sendto)
397 real_sendto = dlsym(RTLD_NEXT, "sendto");
398
399 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck45017722013-10-18 13:04:47 +0200400 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
401 dest_host, dest_port,
402 len, osmo_hexdump(buf, len));
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200403 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck45017722013-10-18 13:04:47 +0200404 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
405 dest_host, dest_port,
406 len, osmo_hexdump(buf, len));
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200407 else
408 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
409
410 return len;
411}
412
413/* override */
414int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
415{
Jacob Erlbeck45017722013-10-18 13:04:47 +0200416 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
417 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200418 uint16_t bvci = msgb_bvci(msg);
419 uint16_t nsei = msgb_nsei(msg);
420
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200421 size_t len = msgb_length(msg);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200422
Jacob Erlbeck45017722013-10-18 13:04:47 +0200423 if (!real_gprs_ns_sendmsg)
424 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
425
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200426 if (nsei == SGSN_NSEI)
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200427 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
428 "msg length %d (%s)\n",
429 bvci, len, __func__);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200430 else
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200431 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
432 "msg length %d (%s)\n",
433 bvci, len, __func__);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200434
Jacob Erlbeck45017722013-10-18 13:04:47 +0200435 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200436}
437
438static void dump_rate_ctr_group(FILE *stream, const char *prefix,
439 struct rate_ctr_group *ctrg)
440{
441 unsigned int i;
442
443 for (i = 0; i < ctrg->desc->num_ctr; i++) {
444 struct rate_ctr *ctr = &ctrg->ctr[i];
445 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
446 fprintf(stream, " %s%s: %llu%s",
447 prefix, ctrg->desc->ctr_desc[i].description,
448 (long long)ctr->current,
449 "\n");
450 };
451}
452
453/* Signal handler for signals from NS layer */
454static int test_signal(unsigned int subsys, unsigned int signal,
455 void *handler_data, void *signal_data)
456{
457 struct ns_signal_data *nssd = signal_data;
458 int rc;
459
460 if (subsys != SS_L_NS)
461 return 0;
462
463 switch (signal) {
464 case S_NS_RESET:
465 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
466 nssd->nsvc->nsvci,
467 gprs_ns_ll_str(nssd->nsvc));
468 break;
469
470 case S_NS_ALIVE_EXP:
471 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
472 nssd->nsvc->nsvci,
473 gprs_ns_ll_str(nssd->nsvc));
474 break;
475
476 case S_NS_BLOCK:
477 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
478 nssd->nsvc->nsvci,
479 gprs_ns_ll_str(nssd->nsvc));
480 break;
481
482 case S_NS_UNBLOCK:
483 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
484 nssd->nsvc->nsvci,
485 gprs_ns_ll_str(nssd->nsvc));
486 break;
487
488 case S_NS_REPLACED:
489 printf("==> got signal NS_REPLACED: 0x%04x/%s",
490 nssd->nsvc->nsvci,
491 gprs_ns_ll_str(nssd->nsvc));
492 printf(" -> 0x%04x/%s\n",
493 nssd->old_nsvc->nsvci,
494 gprs_ns_ll_str(nssd->old_nsvc));
495 break;
496
497 default:
498 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
499 nssd->nsvc->nsvci,
500 gprs_ns_ll_str(nssd->nsvc));
501 break;
502 }
503 printf("\n");
504 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
505 return rc;
506}
507
508static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
509{
510 struct msgb *msg;
511 int ret;
512 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
513 fprintf(stderr, "message too long: %d\n", data_len);
514 return -1;
515 }
516
517 msg = gprs_ns_msgb_alloc();
518 memmove(msg->data, data, data_len);
519 msg->l2h = msg->data;
520 msgb_put(msg, data_len);
521
522 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
523 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
524 osmo_hexdump(data, data_len));
525
526 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
527
528 printf("result (%s) = %d\n\n", text, ret);
529
530 msgb_free(msg);
531
532 return ret;
533}
534
535static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
536{
537 struct gprs_nsvc *nsvc;
538
539 printf("Current NS-VCIs:\n");
540 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
541 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200542 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200543 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck45017722013-10-18 13:04:47 +0200544 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
545 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
546 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200547 );
548 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
549 }
550 printf("\n");
551}
552
553static void test_gbproxy()
554{
555 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
556 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck45017722013-10-18 13:04:47 +0200557 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200558
559 bssgp_nsi = nsi;
560 gbcfg.nsi = bssgp_nsi;
561 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
562
Holger Hans Peter Freyther731097d2014-07-07 14:19:10 +0200563 configure_sgsn_peer(&sgsn_peer);
564 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200565
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200566 printf("=== %s ===\n", __func__);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200567 printf("--- Initialise SGSN ---\n\n");
568
Jacob Erlbeck738b1c82014-07-07 10:46:00 +0200569 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200570 gprs_dump_nsi(nsi);
571
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200572 printf("--- Initialise BSS 1 ---\n\n");
573
574 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
575 setup_bssgp(nsi, &bss_peer[0], 0x1002);
576 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200577 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200578
Jacob Erlbeck45017722013-10-18 13:04:47 +0200579 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
580
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200581 printf("--- Initialise BSS 2 ---\n\n");
582
583 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
584 setup_bssgp(nsi, &bss_peer[1], 0x2002);
585 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200586 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200587
Jacob Erlbeck45017722013-10-18 13:04:47 +0200588 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
589
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200590 printf("--- Move BSS 1 to new port ---\n\n");
591
592 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
593 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200594 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200595
596 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
597
598 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
599 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200600 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200601
602 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
603
604 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
605 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200606 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200607
608 printf("--- Move BSS 2 to new port ---\n\n");
609
610 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
611 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200612 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200613
614 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
615
616 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
617 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200618 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200619
Jacob Erlbeck45017722013-10-18 13:04:47 +0200620 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
621
622 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
623 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200624 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200625
626 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
627
628 setup_bssgp(nsi, &bss_peer[0], 0x1012);
629 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200630 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200631
632 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
633
634 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
635
636 setup_bssgp(nsi, &bss_peer[0], 0x1002);
637 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200638 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200639
640 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
641
642 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
643
644 setup_bssgp(nsi, &bss_peer[0], 0x1002);
645 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200646 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200647
648 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
649
650 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
651
652 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
653
654 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
655
656 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
657
658 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
659
660 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
661
662 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
663
664 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
665
666 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
667
668 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
669
670 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
671
672 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
673
674 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
675
676 setup_bssgp(nsi, &bss_peer[2], 0x1002);
677 gprs_dump_nsi(nsi);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200678 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck45017722013-10-18 13:04:47 +0200679
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200680 gbprox_dump_global(stdout, 0);
Jacob Erlbeckcc4a2aa2013-10-18 22:12:16 +0200681
Jacob Erlbeck45017722013-10-18 13:04:47 +0200682 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
683
684 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
685
686 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
687
688 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
689
690 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
691
Jacob Erlbeckcc4a2aa2013-10-18 22:12:16 +0200692 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
693
694 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
695
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200696 gbprox_dump_global(stdout, 0);
Jacob Erlbeckcc4a2aa2013-10-18 22:12:16 +0200697
Holger Hans Peter Freythera9279872014-07-07 19:22:02 +0200698 gbprox_reset();
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200699 gprs_ns_destroy(nsi);
700 nsi = NULL;
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200701}
702
703static void test_gbproxy_ident_changes()
704{
705 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
706 struct sockaddr_in bss_peer[1] = {{0},};
707 struct sockaddr_in sgsn_peer= {0};
708 uint16_t nsei[2] = {0x1000, 0x2000};
709 uint16_t nsvci[2] = {0x1001, 0x2001};
710 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
711
712 bssgp_nsi = nsi;
713 gbcfg.nsi = bssgp_nsi;
714 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
715
Holger Hans Peter Freyther731097d2014-07-07 14:19:10 +0200716 configure_sgsn_peer(&sgsn_peer);
717 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200718
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200719 printf("=== %s ===\n", __func__);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200720 printf("--- Initialise SGSN ---\n\n");
721
Jacob Erlbeck738b1c82014-07-07 10:46:00 +0200722 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200723 gprs_dump_nsi(nsi);
724
725 printf("--- Initialise BSS 1 ---\n\n");
726
727 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
728 gprs_dump_nsi(nsi);
729
730 printf("--- Setup BVCI 1 ---\n\n");
731
732 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
733 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200734 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200735
736 printf("--- Setup BVCI 2 ---\n\n");
737
738 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
739 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200740 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200741
742 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
743
744 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
745 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
746
747 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
748
749 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
750 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
751
752 printf("--- Change NSEI ---\n\n");
753
754 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
755 gprs_dump_nsi(nsi);
756
757 printf("--- Setup BVCI 1 ---\n\n");
758
759 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
760 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200761 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200762
763 printf("--- Setup BVCI 3 ---\n\n");
764
765 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
766 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200767 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200768
769 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
770
771 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
772 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
773
774 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
775 " (should fail) ---\n\n");
776
777 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200778 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200779 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200780 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200781
782 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
783
784 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
785 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
786
787 printf("--- Change NSVCI ---\n\n");
788
789 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
790 gprs_dump_nsi(nsi);
791
792 printf("--- Setup BVCI 1 ---\n\n");
793
794 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
795 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200796 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200797
798 printf("--- Setup BVCI 4 ---\n\n");
799
800 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
801 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200802 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200803
804 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
805
806 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
807 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
808
809 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
810 " (should fail) ---\n\n");
811
812 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200813 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200814 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200815 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200816
817 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
818
819 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
820 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
821
822 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
823
824 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
825 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
826
Jacob Erlbeckeed33ef2014-07-07 10:45:59 +0200827 gbprox_dump_global(stdout, 0);
828 gbprox_dump_peers(stdout, 0);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200829
Holger Hans Peter Freythera9279872014-07-07 19:22:02 +0200830 gbprox_reset();
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +0200831 gprs_ns_destroy(nsi);
832 nsi = NULL;
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +0200833}
834
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200835static void test_gbproxy_ra_patching()
836{
837 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
838 struct sockaddr_in bss_peer[1] = {{0},};
839 struct sockaddr_in sgsn_peer= {0};
840 struct gprs_ra_id rai_bss =
841 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
842 struct gprs_ra_id rai_sgsn =
843 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
844 struct gprs_ra_id rai_unknown =
845 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeck43037632014-06-06 18:49:23 +0200846 const char *err_msg = NULL;
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200847
848 bssgp_nsi = nsi;
849 gbcfg.nsi = bssgp_nsi;
850 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck2504bc42014-05-19 10:14:58 +0200851 gbcfg.core_mcc = 123;
852 gbcfg.core_mnc = 456;
Jacob Erlbeck5620c6d2014-05-23 20:48:07 +0200853 gbcfg.core_apn = talloc_zero_size(NULL, 100);
854 gbcfg.core_apn_size = gbprox_str_to_apn(gbcfg.core_apn, "foo.bar", 100);
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200855
Holger Hans Peter Freyther731097d2014-07-07 14:19:10 +0200856 configure_sgsn_peer(&sgsn_peer);
857 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200858
Jacob Erlbeck43037632014-06-06 18:49:23 +0200859 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
860 if (gbprox_set_patch_filter(gbcfg.match_re, &err_msg) != 0) {
861 fprintf(stderr, "Failed to compile RE '%s': %s\n",
862 gbcfg.match_re, err_msg);
863 exit(1);
864 }
865
866
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200867 printf("=== %s ===\n", __func__);
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200868 printf("--- Initialise SGSN ---\n\n");
869
870 connect_sgsn(nsi, &sgsn_peer);
871 gprs_dump_nsi(nsi);
872
873 printf("--- Initialise BSS 1 ---\n\n");
874
875 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
876 setup_bssgp(nsi, &bss_peer[0], 0x1002);
877 gprs_dump_nsi(nsi);
878 gbprox_dump_peers(stdout, 0);
879
880 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
881
882 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
883 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
884
885 gbprox_dump_global(stdout, 0);
886 gbprox_dump_peers(stdout, 0);
887
888 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
889
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200890 send_ns_unitdata(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200891 bssgp_attach_req, sizeof(bssgp_attach_req));
892
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200893 send_ns_unitdata(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200894 bssgp_attach_acc, sizeof(bssgp_attach_acc));
895
Jacob Erlbeck386621c2014-06-27 11:55:04 +0200896 /* Replace APN (1) */
897 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
898 &bss_peer[0], 0x1002,
899 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200900
Jacob Erlbeckab7366f2014-06-06 18:47:36 +0200901 send_ns_unitdata(nsi, "GMM INFO", &sgsn_peer, 0x1002,
902 bssgp_gmm_information, sizeof(bssgp_gmm_information));
903
Jacob Erlbeck386621c2014-06-27 11:55:04 +0200904 /* Replace APN (2) */
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200905 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REPLACE APN)",
906 &bss_peer[0], 0x1002,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200907 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
908
Jacob Erlbeck5620c6d2014-05-23 20:48:07 +0200909 gbcfg.core_apn[0] = 0;
910 gbcfg.core_apn_size = 0;
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200911
912 /* Remove APN */
Jacob Erlbeck03a2ee22014-07-09 23:19:11 +0200913 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
914 &bss_peer[0], 0x1002,
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200915 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
916
Jacob Erlbeck386621c2014-06-27 11:55:04 +0200917 gbprox_dump_peers(stdout, 0);
918
Jacob Erlbeckbf6020f2014-06-19 10:23:50 +0200919 /* Detach */
920 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
921 bssgp_detach_req, sizeof(bssgp_detach_req));
922
923 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
924 bssgp_detach_acc, sizeof(bssgp_detach_acc));
925
Jacob Erlbeck386621c2014-06-27 11:55:04 +0200926 gbprox_dump_peers(stdout, 0);
927
928 printf("--- RA update ---\n\n");
929
930 send_ns_unitdata(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
931 bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req));
932
933 send_ns_unitdata(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
934 bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc));
935
936 /* Remove APN */
937 send_ns_unitdata(nsi, "ACT PDP CTX REQ (REMOVE APN)",
938 &bss_peer[0], 0x1002,
939 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
940
941 gbprox_dump_peers(stdout, 0);
942
943 /* Detach */
944 send_ns_unitdata(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
945 bssgp_detach_req, sizeof(bssgp_detach_req));
946
947 send_ns_unitdata(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
948 bssgp_detach_acc, sizeof(bssgp_detach_acc));
949
950
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200951 gbprox_dump_global(stdout, 0);
952 gbprox_dump_peers(stdout, 0);
953
954 printf("--- Bad cases ---\n\n");
955
Jacob Erlbeck43037632014-06-06 18:49:23 +0200956 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckbf6020f2014-06-19 10:23:50 +0200957 send_ns_unitdata(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
958 bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
959
Jacob Erlbeck90a1fd12014-05-27 13:49:04 +0200960 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200961 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
962
963 gbprox_dump_global(stdout, 0);
964 gbprox_dump_peers(stdout, 0);
965
Holger Hans Peter Freythera9279872014-07-07 19:22:02 +0200966 gbprox_reset();
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200967 gprs_ns_destroy(nsi);
968 nsi = NULL;
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +0200969}
970
Jacob Erlbeck077abce2014-07-01 12:41:13 +0200971/* TODO: Move tlv testing to libosmocore */
972int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
973int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
974 uint8_t **value);
975int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
976 size_t *value_len);
977int lv_shift(uint8_t **data, size_t *data_len,
978 uint8_t **value, size_t *value_len);
979
980static void check_tlv_match(uint8_t **data, size_t *data_len,
981 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
982{
983 uint8_t *value;
984 size_t value_len;
985 int rc;
986
987 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
988 OSMO_ASSERT(rc == 0);
989
990 rc = tlv_match(data, data_len, tag, &value, &value_len);
991 OSMO_ASSERT(rc == value_len + 2);
992 OSMO_ASSERT(value_len == exp_len);
993 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
994}
995
996static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
997 uint8_t tag, size_t len, const uint8_t *exp_val)
998{
999 uint8_t *value;
1000 int rc;
1001
1002 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1003 OSMO_ASSERT(rc == 0);
1004
1005 rc = tv_fixed_match(data, data_len, tag, len, &value);
1006 OSMO_ASSERT(rc == len + 1);
1007 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1008}
1009
1010static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1011 size_t len, const uint8_t *exp_val)
1012{
1013 uint8_t *value;
1014 int rc;
1015
1016 rc = v_fixed_shift(data, data_len, len, &value);
1017 OSMO_ASSERT(rc == len);
1018 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1019}
1020
1021static void check_lv_shift(uint8_t **data, size_t *data_len,
1022 size_t exp_len, const uint8_t *exp_val)
1023{
1024 uint8_t *value;
1025 size_t value_len;
1026 int rc;
1027
1028 rc = lv_shift(data, data_len, &value, &value_len);
1029 OSMO_ASSERT(rc == value_len + 1);
1030 OSMO_ASSERT(value_len == exp_len);
1031 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1032}
1033
1034static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1035 const uint8_t *test_data)
1036{
1037 uint8_t buf[300] = {0};
1038
1039 uint8_t *unchanged_ptr = buf - 1;
1040 size_t unchanged_len = 0xdead;
1041 size_t tmp_data_len = data_len;
1042 uint8_t *value = unchanged_ptr;
1043 size_t value_len = unchanged_len;
1044 uint8_t *data = buf;
1045
1046 OSMO_ASSERT(data_len <= sizeof(buf));
1047
1048 tlv_put(data, tag, len, test_data);
1049 if (data_len < len + 2) {
1050 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1051 tag, &value, &value_len));
1052 OSMO_ASSERT(tmp_data_len == 0);
1053 OSMO_ASSERT(data == buf + data_len);
1054 OSMO_ASSERT(value == unchanged_ptr);
1055 OSMO_ASSERT(value_len == unchanged_len);
1056 } else {
1057 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1058 tag, &value, &value_len));
1059 OSMO_ASSERT(value != unchanged_ptr);
1060 OSMO_ASSERT(value_len != unchanged_len);
1061 }
1062}
1063
1064static void check_tv_fixed_match_data_len(size_t data_len,
1065 uint8_t tag, size_t len,
1066 const uint8_t *test_data)
1067{
1068 uint8_t buf[300] = {0};
1069
1070 uint8_t *unchanged_ptr = buf - 1;
1071 size_t tmp_data_len = data_len;
1072 uint8_t *value = unchanged_ptr;
1073 uint8_t *data = buf;
1074
1075 OSMO_ASSERT(data_len <= sizeof(buf));
1076
1077 tv_fixed_put(data, tag, len, test_data);
1078
1079 if (data_len < len + 1) {
1080 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1081 tag, len, &value));
1082 OSMO_ASSERT(tmp_data_len == 0);
1083 OSMO_ASSERT(data == buf + data_len);
1084 OSMO_ASSERT(value == unchanged_ptr);
1085 } else {
1086 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1087 tag, len, &value));
1088 OSMO_ASSERT(value != unchanged_ptr);
1089 }
1090}
1091
1092static void check_v_fixed_shift_data_len(size_t data_len,
1093 size_t len, const uint8_t *test_data)
1094{
1095 uint8_t buf[300] = {0};
1096
1097 uint8_t *unchanged_ptr = buf - 1;
1098 size_t tmp_data_len = data_len;
1099 uint8_t *value = unchanged_ptr;
1100 uint8_t *data = buf;
1101
1102 OSMO_ASSERT(data_len <= sizeof(buf));
1103
1104 memcpy(data, test_data, len);
1105
1106 if (data_len < len) {
1107 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1108 len, &value));
1109 OSMO_ASSERT(tmp_data_len == 0);
1110 OSMO_ASSERT(data == buf + data_len);
1111 OSMO_ASSERT(value == unchanged_ptr);
1112 } else {
1113 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1114 len, &value));
1115 OSMO_ASSERT(value != unchanged_ptr);
1116 }
1117}
1118
1119static void check_lv_shift_data_len(size_t data_len,
1120 size_t len, const uint8_t *test_data)
1121{
1122 uint8_t buf[300] = {0};
1123
1124 uint8_t *unchanged_ptr = buf - 1;
1125 size_t unchanged_len = 0xdead;
1126 size_t tmp_data_len = data_len;
1127 uint8_t *value = unchanged_ptr;
1128 size_t value_len = unchanged_len;
1129 uint8_t *data = buf;
1130
1131 lv_put(data, len, test_data);
1132 if (data_len < len + 1) {
1133 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1134 &value, &value_len));
1135 OSMO_ASSERT(tmp_data_len == 0);
1136 OSMO_ASSERT(data == buf + data_len);
1137 OSMO_ASSERT(value == unchanged_ptr);
1138 OSMO_ASSERT(value_len == unchanged_len);
1139 } else {
1140 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1141 &value, &value_len));
1142 OSMO_ASSERT(value != unchanged_ptr);
1143 OSMO_ASSERT(value_len != unchanged_len);
1144 }
1145}
1146
1147static void test_tlv_shift_functions()
1148{
1149 uint8_t test_data[1024];
1150 uint8_t buf[1024];
1151 uint8_t *data_end;
1152 int i, len;
1153 uint8_t *data;
1154 size_t data_len;
1155 const uint8_t tag = 0x1a;
1156
1157 printf("Test shift functions\n");
1158
1159 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1160 test_data[i] = (uint8_t)i;
1161
1162 for (len = 0; len < 256; len++) {
1163 const int iterations = sizeof(buf) / (len + 2) / 4;
1164
1165 memset(buf, 0xee, sizeof(buf));
1166 data_end = data = buf;
1167
1168 for (i = 0; i < iterations; i++) {
1169 data_end = tlv_put(data_end, tag, len, test_data);
1170 data_end = tv_fixed_put(data_end, tag, len, test_data);
1171 /* v_fixed_put */
1172 memcpy(data_end, test_data, len);
1173 data_end += len;
1174 data_end = lv_put(data_end, len, test_data);
1175 }
1176
1177 data_len = data_end - data;
1178 OSMO_ASSERT(data_len <= sizeof(buf));
1179
1180 for (i = 0; i < iterations; i++) {
1181 check_tlv_match(&data, &data_len, tag, len, test_data);
1182 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1183 check_v_fixed_shift(&data, &data_len, len, test_data);
1184 check_lv_shift(&data, &data_len, len, test_data);
1185 }
1186
1187 OSMO_ASSERT(data == data_end);
1188
1189 /* Test at end of data */
1190
1191 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1192 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1193 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1194 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1195
1196 /* Test invalid data_len */
1197 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1198 check_tlv_match_data_len(data_len, tag, len, test_data);
1199 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1200 check_v_fixed_shift_data_len(data_len, len, test_data);
1201 check_lv_shift_data_len(data_len, len, test_data);
1202 }
1203 }
1204}
Jacob Erlbeckb440bf82014-07-03 13:28:13 +02001205static struct log_info_cat gprs_categories[] = {
1206 [DGPRS] = {
1207 .name = "DGPRS",
1208 .description = "GPRS Packet Service",
1209 .enabled = 1, .loglevel = LOGL_DEBUG,
1210 },
1211 [DNS] = {
1212 .name = "DNS",
1213 .description = "GPRS Network Service (NS)",
1214 .enabled = 1, .loglevel = LOGL_INFO,
1215 },
1216 [DBSSGP] = {
1217 .name = "DBSSGP",
1218 .description = "GPRS BSS Gateway Protocol (BSSGP)",
1219 .enabled = 1, .loglevel = LOGL_DEBUG,
1220 },
Holger Hans Peter Freyther89276422014-07-07 19:48:14 +02001221};
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +02001222
Holger Hans Peter Freyther89276422014-07-07 19:48:14 +02001223static struct log_info info = {
Jacob Erlbeckb440bf82014-07-03 13:28:13 +02001224 .cat = gprs_categories,
1225 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther89276422014-07-07 19:48:14 +02001226};
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +02001227
1228int main(int argc, char **argv)
1229{
1230 osmo_init_logging(&info);
1231 log_set_use_color(osmo_stderr_target, 0);
1232 log_set_print_filename(osmo_stderr_target, 0);
1233 osmo_signal_register_handler(SS_L_NS, &test_signal, NULL);
1234
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +02001235 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeckb440bf82014-07-03 13:28:13 +02001236 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
1237 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +02001238
1239 rate_ctr_init(NULL);
1240
1241 setlinebuf(stdout);
1242
1243 printf("===== GbProxy test START\n");
Jacob Erlbeck077abce2014-07-01 12:41:13 +02001244 test_tlv_shift_functions();
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +02001245 test_gbproxy();
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +02001246 test_gbproxy_ident_changes();
Jacob Erlbeckeb3102e2014-07-07 10:46:01 +02001247 test_gbproxy_ra_patching();
Jacob Erlbeck67f03bd2013-10-24 12:48:55 +02001248 printf("===== GbProxy test END\n\n");
Jacob Erlbeck76fa57a2013-10-15 12:00:26 +02001249
1250 exit(EXIT_SUCCESS);
1251}