blob: 67e4d714e769b447e3d9b18fad95f0067a0e2e58 [file] [log] [blame]
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001/* test routines for gbproxy
2 * send NS messages to the gbproxy and dumps what happens
3 * (C) 2013 by sysmocom s.f.m.c. GmbH
4 * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
5 */
6
7#undef _GNU_SOURCE
8#define _GNU_SOURCE
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <string.h>
14#include <getopt.h>
15#include <dlfcn.h>
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020016#include <time.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020017#include <sys/types.h>
18#include <sys/socket.h>
19
20#include <osmocom/core/msgb.h>
21#include <osmocom/core/application.h>
22#include <osmocom/core/utils.h>
23#include <osmocom/core/logging.h>
24#include <osmocom/core/talloc.h>
25#include <osmocom/core/signal.h>
26#include <osmocom/core/rate_ctr.h>
Jacob Erlbeckb1381062014-07-01 12:41:13 +020027#include <osmocom/gsm/tlv.h>
Jacob Erlbeck59748e62014-08-11 17:26:21 +020028#include <osmocom/gsm/gsm_utils.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020029#include <osmocom/gprs/gprs_msgb.h>
30#include <osmocom/gprs/gprs_ns.h>
31#include <osmocom/gprs/gprs_bssgp.h>
32
33#include <openbsc/gb_proxy.h>
Holger Hans Peter Freyther7127b022014-08-04 11:52:52 +020034#include <openbsc/gprs_utils.h>
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +020035#include <openbsc/gprs_llc.h>
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020036#include <openbsc/debug.h>
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020037
38#define REMOTE_BSS_ADDR 0x01020304
39#define REMOTE_SGSN_ADDR 0x05060708
40
Jacob Erlbeck2082afa2013-10-18 13:04:47 +020041#define SGSN_NSEI 0x0100
Jacob Erlbeck51a869c2013-10-15 12:00:26 +020042
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +020043struct gbproxy_config gbcfg = {0};
44
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020045static int dump_global(FILE *stream, int indent)
46{
47 unsigned int i;
48 const struct rate_ctr_group_desc *desc;
49 int rc;
50
51 rc = fprintf(stream, "%*sGbproxy global:\n", indent, "");
52 if (rc < 0)
53 return rc;
54
55 desc = gbcfg.ctrg->desc;
56
57 for (i = 0; i < desc->num_ctr; i++) {
58 struct rate_ctr *ctr = &gbcfg.ctrg->ctr[i];
59 if (ctr->current) {
60 rc = fprintf(stream, "%*s %s: %llu\n",
61 indent, "",
62 desc->ctr_desc[i].description,
63 (long long)ctr->current);
64
65 if (rc < 0)
66 return rc;
67 }
68 }
69
70 return 0;
71}
72
Jacob Erlbeck7b821d02014-08-08 08:37:37 +020073static int dump_peers(FILE *stream, int indent, time_t now,
74 struct gbproxy_config *cfg)
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020075{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020076 struct gbproxy_peer *peer;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020077 struct gprs_ra_id raid;
78 unsigned int i;
79 const struct rate_ctr_group_desc *desc;
80 int rc;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020081
82 rc = fprintf(stream, "%*sPeers:\n", indent, "");
83 if (rc < 0)
84 return rc;
85
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +020086 llist_for_each_entry(peer, &cfg->bts_peers, list) {
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020087 struct gbproxy_tlli_info *tlli_info;
88 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +020089 gsm48_parse_ra(&raid, peer->ra);
90
91 rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, "
92 "RAI %u-%u-%u-%u\n",
93 indent, "",
94 peer->nsei, peer->bvci,
95 peer->blocked ? "" : "not ",
96 raid.mcc, raid.mnc, raid.lac, raid.rac);
97
98 if (rc < 0)
99 return rc;
100
101 desc = peer->ctrg->desc;
102
103 for (i = 0; i < desc->num_ctr; i++) {
104 struct rate_ctr *ctr = &peer->ctrg->ctr[i];
105 if (ctr->current) {
106 rc = fprintf(stream, "%*s %s: %llu\n",
107 indent, "",
108 desc->ctr_desc[i].description,
109 (long long)ctr->current);
110
111 if (rc < 0)
112 return rc;
113 }
114 }
115
116 fprintf(stream, "%*s TLLI-Cache: %d\n",
117 indent, "", state->enabled_tllis_count);
118 llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
119 char mi_buf[200];
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200120 time_t age = now ? now - tlli_info->timestamp : 0;
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200121 if (tlli_info->mi_data_len > 0) {
122 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
123 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
124 tlli_info->mi_data,
125 tlli_info->mi_data_len);
126 } else {
127 snprintf(mi_buf, sizeof(mi_buf), "(none)");
128 }
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200129 fprintf(stream, "%*s TLLI %08x",
Jacob Erlbeck9057bc32014-08-12 16:30:30 +0200130 indent, "", tlli_info->tlli.current);
131 if (tlli_info->tlli.assigned)
132 fprintf(stream, "/%08x", tlli_info->tlli.assigned);
133 if (tlli_info->sgsn_tlli.current) {
134 fprintf(stream, " -> %08x",
135 tlli_info->sgsn_tlli.current);
136 if (tlli_info->sgsn_tlli.assigned)
137 fprintf(stream, "/%08x",
138 tlli_info->sgsn_tlli.assigned);
139 }
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200140 rc = fprintf(stream, ", IMSI %s, AGE %d\n",
141 mi_buf, (int)age);
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200142 if (rc < 0)
143 return rc;
144 }
145 }
146
147 return 0;
148}
149
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200150/* DTAP - Attach Request */
151static const unsigned char dtap_attach_req[] = {
152 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, 0x08, 0x02,
153 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, 0x11, 0x22,
154 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, 0xb3, 0x43,
155 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, 0x9a,
156 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, 0xc8,
157 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200158};
159
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200160/* DTAP - Identity Request */
161static const unsigned char dtap_identity_req[] = {
162 0x08, 0x15, 0x01
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200163};
164
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200165/* DTAP - Identity Response */
166static const unsigned char dtap_identity_resp[] = {
167 0x08, 0x16, 0x08, 0x11, 0x12, 0x13, 0x14, 0x15,
168 0x16, 0x17, 0x18
Jacob Erlbeck690768a2014-08-06 15:16:45 +0200169};
170
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200171/* DTAP - Attach Accept */
172static const unsigned char dtap_attach_acc[] = {
173 0x08, 0x02, 0x01, 0x49, 0x04, 0x21, 0x63, 0x54,
174 0x40, 0x50, 0x60, 0x19, 0xcd, 0xd7, 0x08, 0x17,
175 0x16, 0x18, 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200176};
177
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200178/* DTAP - Attach Complete */
179static const unsigned char dtap_attach_complete[] = {
180 0x08, 0x03
Jacob Erlbeck59748e62014-08-11 17:26:21 +0200181};
182
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200183/* DTAP - GMM Information */
184static const unsigned char dtap_gmm_information[] = {
185 0x08, 0x21
Jacob Erlbeck11669742014-06-06 18:47:36 +0200186};
187
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200188/* DTAP - Routing Area Update Request */
189static const unsigned char dtap_ra_upd_req[] = {
190 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, 0x40, 0x50,
191 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, 0x57, 0x2b,
192 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, 0x50, 0xc8,
193 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, 0x48, 0x02,
194 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, 0x00, 0x19,
195 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, 0x07, 0x04,
196 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, 0x20, 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200197};
198
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200199/* DTAP - Routing Area Update Accept */
200static const unsigned char dtap_ra_upd_acc[] = {
201 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54,
202 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18,
203 0x05, 0xf4, 0xef, 0xe2, 0xb7, 0x00, 0x17, 0x16,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200204};
205
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200206/* DTAP - Activate PDP Context Request */
207static const unsigned char dtap_act_pdp_ctx_req[] = {
208 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200209 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03,
211 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21,
212 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00,
213 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00,
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200214 0x00
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200215};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200216
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200217/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200218/* normal detach, power_off = 1 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200219static const unsigned char dtap_detach_po_req[] = {
220 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
221 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200222};
223
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200224/* DTAP - Detach Request (MO) */
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +0200225/* normal detach, power_off = 0 */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200226static const unsigned char dtap_detach_req[] = {
227 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
228 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200229};
230
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200231/* DTAP - Detach Accept */
232static const unsigned char dtap_detach_acc[] = {
233 0x08, 0x06, 0x00
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +0200234};
235
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +0200236/* GPRS-LLC - SAPI: LLGMM, U, XID */
237static const unsigned char llc_u_xid_ul[] = {
238 0x41, 0xfb, 0x01, 0x00, 0x0e, 0x00, 0x64, 0x11,
239 0x05, 0x16, 0x01, 0x90, 0x66, 0xb3, 0x28
240};
241
242/* GPRS-LLC - SAPI: LLGMM, U, XID */
243static const unsigned char llc_u_xid_dl[] = {
244 0x41, 0xfb, 0x30, 0x84, 0x10, 0x61, 0xb6, 0x64,
245 0xe4, 0xa9, 0x1a, 0x9e
246};
247
248/* GPRS-LLC - SAPI: LL11, UI, NSAPI 5, DNS query */
249static const unsigned char llc_ui_ll11_dns_query_ul[] = {
250 0x0b, 0xc0, 0x01, 0x65, 0x00, 0x00, 0x00, 0x45,
251 0x00, 0x00, 0x38, 0x95, 0x72, 0x00, 0x00, 0x45,
252 0x11, 0x20, 0x85, 0x0a, 0xc0, 0x07, 0xe4, 0xac,
253 0x10, 0x01, 0x0a, 0xad, 0xab, 0x00, 0x35, 0x00,
254 0x24, 0x0e, 0x1c, 0x3b, 0xe0, 0x01, 0x00, 0x00,
255 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
256 0x6d, 0x05, 0x68, 0x65, 0x69, 0x73, 0x65, 0x02,
257 0x64, 0x65, 0x00, 0x00, 0x01, 0x00, 0x01, 0x47,
258 0x8f, 0x07
259};
260
261/* GPRS-LLC - SAPI: LL11, UI, NSAPI 5, DNS query */
262static const unsigned char llc_ui_ll11_dns_resp_dl[] = {
263 0x4b, 0xc0, 0x01, 0x65, 0x00, 0x00, 0x00, 0x45,
264 0x00, 0x00, 0xc6, 0x00, 0x00, 0x40, 0x00, 0x3e,
265 0x11, 0x7c, 0x69, 0xac, 0x10, 0x01, 0x0a, 0x0a,
266 0xc0, 0x07, 0xe4, 0x00, 0x35, 0xad, 0xab, 0x00,
267 0xb2, 0x74, 0x4e, 0x3b, 0xe0, 0x81, 0x80, 0x00,
268 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x01,
269 0x6d, 0x05, 0x68, 0x65, 0x69, 0x73, 0x65, 0x02,
270 0x64, 0x65, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0,
271 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e,
272 0x10, 0x00, 0x04, 0xc1, 0x63, 0x90, 0x58, 0xc0,
273 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e,
274 0x10, 0x00, 0x16, 0x03, 0x6e, 0x73, 0x32, 0x0c,
275 0x70, 0x6f, 0x70, 0x2d, 0x68, 0x61, 0x6e, 0x6e,
276 0x6f, 0x76, 0x65, 0x72, 0x03, 0x6e, 0x65, 0x74,
277 0x00, 0xc0, 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00,
278 0x00, 0x0e, 0x10, 0x00, 0x10, 0x02, 0x6e, 0x73,
279 0x01, 0x73, 0x08, 0x70, 0x6c, 0x75, 0x73, 0x6c,
280 0x69, 0x6e, 0x65, 0xc0, 0x14, 0xc0, 0x0e, 0x00,
281 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00,
282 0x05, 0x02, 0x6e, 0x73, 0xc0, 0x0e, 0xc0, 0x0e,
283 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10,
284 0x00, 0x05, 0x02, 0x6e, 0x73, 0xc0, 0x5f, 0xc0,
285 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e,
286 0x10, 0x00, 0x12, 0x02, 0x6e, 0x73, 0x0c, 0x70,
287 0x6f, 0x70, 0x2d, 0x68, 0x61, 0x6e, 0x6e, 0x6f,
288 0x76, 0x65, 0x72, 0xc0, 0x14, 0xaa, 0xdf, 0x31
289};
290
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200291static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
292 struct sockaddr_in *peer, const unsigned char* data,
293 size_t data_len);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200294
295static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
296 enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
297{
298 /* GPRS Network Service, PDU type: NS_RESET,
299 */
300 unsigned char msg[12] = {
301 0x02, 0x00, 0x81, 0x01, 0x01, 0x82, 0x11, 0x22,
302 0x04, 0x82, 0x11, 0x22
303 };
304
305 msg[3] = cause;
306 msg[6] = nsvci / 256;
307 msg[7] = nsvci % 256;
308 msg[10] = nsei / 256;
309 msg[11] = nsei % 256;
310
311 gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
312}
313
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200314static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
315 uint16_t nsvci, uint16_t nsei)
316{
317 /* GPRS Network Service, PDU type: NS_RESET_ACK,
318 */
319 unsigned char msg[9] = {
320 0x03, 0x01, 0x82, 0x11, 0x22,
321 0x04, 0x82, 0x11, 0x22
322 };
323
324 msg[3] = nsvci / 256;
325 msg[4] = nsvci % 256;
326 msg[7] = nsei / 256;
327 msg[8] = nsei % 256;
328
329 gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
330}
331
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200332static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
333{
334 /* GPRS Network Service, PDU type: NS_ALIVE */
335 unsigned char msg[1] = {
336 0x0a
337 };
338
339 gprs_process_message(nsi, "ALIVE", src_addr, msg, sizeof(msg));
340}
341
342static void send_ns_alive_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
343{
344 /* GPRS Network Service, PDU type: NS_ALIVE_ACK */
345 unsigned char msg[1] = {
346 0x0b
347 };
348
349 gprs_process_message(nsi, "ALIVE_ACK", src_addr, msg, sizeof(msg));
350}
351
352static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
353{
354 /* GPRS Network Service, PDU type: NS_UNBLOCK */
355 unsigned char msg[1] = {
356 0x06
357 };
358
359 gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
360}
361
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200362static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
363{
364 /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
365 unsigned char msg[1] = {
366 0x07
367 };
368
369 gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
370}
371
372static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
373 struct sockaddr_in *src_addr, uint16_t nsbvci,
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200374 const unsigned char *bssgp_msg, size_t bssgp_msg_size)
375{
376 /* GPRS Network Service, PDU type: NS_UNITDATA */
377 unsigned char msg[4096] = {
378 0x00, 0x00, 0x00, 0x00
379 };
380
381 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg) - 4);
382
383 msg[2] = nsbvci / 256;
384 msg[3] = nsbvci % 256;
385 memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
386
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200387 gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200388}
389
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200390static void send_bssgp_ul_unitdata(
391 struct gprs_ns_inst *nsi, const char *text,
392 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
393 struct gprs_ra_id *raid, uint16_t cell_id,
394 const uint8_t *llc_msg, size_t llc_msg_size)
395{
396 /* GPRS Network Service, PDU type: NS_UNITDATA */
397 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
398 unsigned char msg[4096] = {
399 0x01, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
400 0x08, 0x88, /* RAI */ 0x11, 0x22, 0x33, 0x40, 0x50, 0x60,
401 /* CELL ID */ 0x00, 0x00, 0x00, 0x80, 0x0e, /* LLC LEN */ 0x00, 0x00,
402 };
403
404 size_t bssgp_msg_size = 23 + llc_msg_size;
405
406 OSMO_ASSERT(bssgp_msg_size <= sizeof(msg));
407
408 gsm48_construct_ra(msg + 10, raid);
409 msg[1] = (uint8_t)(tlli >> 24);
410 msg[2] = (uint8_t)(tlli >> 16);
411 msg[3] = (uint8_t)(tlli >> 8);
412 msg[4] = (uint8_t)(tlli >> 0);
413 msg[16] = cell_id / 256;
414 msg[17] = cell_id % 256;
415 msg[21] = llc_msg_size / 256;
416 msg[22] = llc_msg_size % 256;
417 memcpy(msg + 23, llc_msg, llc_msg_size);
418
419 send_ns_unitdata(nsi, text ? text : "BSSGP UL UNITDATA",
420 src_addr, nsbvci, msg, bssgp_msg_size);
421}
422
423static void send_bssgp_dl_unitdata(
424 struct gprs_ns_inst *nsi, const char *text,
425 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
426 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
427 const uint8_t *llc_msg, size_t llc_msg_size)
428{
429 /* Base Station Subsystem GPRS Protocol: DL_UNITDATA */
430 unsigned char msg[4096] = {
431 0x00, /* TLLI */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20,
432 0x16, 0x82, 0x02, 0x58,
433 };
434 unsigned char racap_drx[] = {
435 0x13, 0x99, 0x18, 0xb3, 0x43, 0x2b, 0x25, 0x96,
436 0x62, 0x00, 0x60, 0x80, 0x9a, 0xc2, 0xc6, 0x62,
437 0x00, 0x60, 0x80, 0xba, 0xc8, 0xc6, 0x62, 0x00,
438 0x60, 0x80, 0x00, 0x0a, 0x82, 0x08, 0x02
439 };
440
441 size_t bssgp_msg_size = 0;
442
443 OSMO_ASSERT(51 + imsi_size + llc_msg_size <= sizeof(msg));
444
445 msg[1] = (uint8_t)(tlli >> 24);
446 msg[2] = (uint8_t)(tlli >> 16);
447 msg[3] = (uint8_t)(tlli >> 8);
448 msg[4] = (uint8_t)(tlli >> 0);
449
450 bssgp_msg_size = 12;
451
452 if (with_racap_drx) {
453 memcpy(msg + bssgp_msg_size, racap_drx, sizeof(racap_drx));
454 bssgp_msg_size += sizeof(racap_drx);
455 }
456
457 if (imsi) {
458 OSMO_ASSERT(imsi_size <= 127);
459 msg[bssgp_msg_size] = BSSGP_IE_IMSI;
460 msg[bssgp_msg_size + 1] = 0x80 | imsi_size;
461 memcpy(msg + bssgp_msg_size + 2, imsi, imsi_size);
462 bssgp_msg_size += 2 + imsi_size;
463 }
464
465 if ((bssgp_msg_size % 4) != 0) {
466 size_t abytes = (4 - (bssgp_msg_size + 2) % 4) % 4;
467 msg[bssgp_msg_size] = BSSGP_IE_ALIGNMENT;
468 msg[bssgp_msg_size + 1] = 0x80 | abytes;
469 memset(msg + bssgp_msg_size + 2, 0, abytes);
470 bssgp_msg_size += 2 + abytes;
471 }
472
473 msg[bssgp_msg_size] = BSSGP_IE_LLC_PDU;
474 if (llc_msg_size < 128) {
475 msg[bssgp_msg_size + 1] = 0x80 | llc_msg_size;
476 bssgp_msg_size += 2;
477 } else {
478 msg[bssgp_msg_size + 1] = llc_msg_size / 256;
479 msg[bssgp_msg_size + 2] = llc_msg_size % 256;
480 bssgp_msg_size += 3;
481 }
482 memcpy(msg + bssgp_msg_size, llc_msg, llc_msg_size);
483 bssgp_msg_size += llc_msg_size;
484
485
486 send_ns_unitdata(nsi, text ? text : "BSSGP DL UNITDATA",
487 src_addr, nsbvci, msg, bssgp_msg_size);
488}
489
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200490static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
491 uint16_t bvci)
492{
493 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
494 * BSSGP RESET */
Jacob Erlbeckda4b4922014-08-06 12:38:10 +0200495 unsigned char msg[18] = {
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200496 0x22, 0x04, 0x82, 0x4a,
Jacob Erlbeckdef03912014-06-02 10:48:59 +0200497 0x2e, 0x07, 0x81, 0x08, 0x08, 0x88, 0x11, 0x22,
498 0x33, 0x40, 0x50, 0x60, 0x10, 0x00
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200499 };
500
501 msg[3] = bvci / 256;
502 msg[4] = bvci % 256;
503
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200504 send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
505}
506
507static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
508 struct sockaddr_in *src_addr, uint16_t bvci)
509{
510 /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
511 * BSSGP RESET_ACK */
512 static unsigned char msg[5] = {
513 0x23, 0x04, 0x82, 0x00,
514 0x00
515 };
516
517 msg[3] = bvci / 256;
518 msg[4] = bvci % 256;
519
520 send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200521}
522
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200523static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
524 struct sockaddr_in *src_addr,
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200525 uint32_t tlli,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200526 struct gprs_ra_id *raid)
527{
528 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
529 unsigned char msg[15] = {
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200530 0x0b, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x1b,
531 0x86, /* RAI */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200532 };
533
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200534 msg[3] = (uint8_t)(tlli >> 24);
535 msg[4] = (uint8_t)(tlli >> 16);
536 msg[5] = (uint8_t)(tlli >> 8);
537 msg[6] = (uint8_t)(tlli >> 0);
538
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200539 gsm48_construct_ra(msg + 9, raid);
540
541 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
542}
543
544static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
545 struct sockaddr_in *src_addr,
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200546 uint32_t tlli,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200547 struct gprs_ra_id *raid)
548{
549 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
550 unsigned char msg[18] = {
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200551 0x0c, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x1b,
552 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1d,
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200553 0x81, 0x01
554 };
555
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200556 msg[3] = (uint8_t)(tlli >> 24);
557 msg[4] = (uint8_t)(tlli >> 16);
558 msg[5] = (uint8_t)(tlli >> 8);
559 msg[6] = (uint8_t)(tlli >> 0);
560
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +0200561 gsm48_construct_ra(msg + 9, raid);
562
563 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
564}
565
Jacob Erlbeck299389a2014-08-21 16:34:18 +0200566static void send_bssgp_llc_discarded(struct gprs_ns_inst *nsi,
567 struct sockaddr_in *src_addr,
568 uint16_t bvci, uint32_t tlli,
569 unsigned n_frames, unsigned n_octets)
570{
571 /* Base Station Subsystem GPRS Protocol: LLC-DISCARDED (0x2c) */
572 unsigned char msg[] = {
573 0x2c, 0x1f, 0x84, /* TLLI */ 0xff, 0xff, 0xff, 0xff, 0x0f,
574 0x81, /* n frames */ 0xff, 0x04, 0x82, /* BVCI */ 0xff, 0xff, 0x25, 0x83,
575 /* n octets */ 0xff, 0xff, 0xff
576 };
577
578 msg[3] = (uint8_t)(tlli >> 24);
579 msg[4] = (uint8_t)(tlli >> 16);
580 msg[5] = (uint8_t)(tlli >> 8);
581 msg[6] = (uint8_t)(tlli >> 0);
582 msg[9] = (uint8_t)(n_frames);
583 msg[12] = (uint8_t)(bvci >> 8);
584 msg[13] = (uint8_t)(bvci >> 0);
585 msg[16] = (uint8_t)(n_octets >> 16);
586 msg[17] = (uint8_t)(n_octets >> 8);
587 msg[18] = (uint8_t)(n_octets >> 0);
588
589 send_ns_unitdata(nsi, "LLC_DISCARDED", src_addr, 0, msg, sizeof(msg));
590}
591
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200592static void send_llc_ul_ui(
593 struct gprs_ns_inst *nsi, const char *text,
594 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
595 struct gprs_ra_id *raid, uint16_t cell_id,
596 unsigned sapi, unsigned nu,
597 const uint8_t *msg, size_t msg_size)
598{
599 unsigned char llc_msg[4096] = {
600 0x00, 0xc0, 0x01
601 };
602
603 size_t llc_msg_size = 3 + msg_size + 3;
604 uint8_t e_bit = 0;
605 uint8_t pm_bit = 1;
606 unsigned fcs;
607
608 nu &= 0x01ff;
609
610 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
611
612 llc_msg[0] = (sapi & 0x0f);
613 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
614 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
615
616 memcpy(llc_msg + 3, msg, msg_size);
617
618 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
619 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
620 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
621 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
622
623 send_bssgp_ul_unitdata(nsi, text ? text : "LLC UI",
624 src_addr, nsbvci, tlli, raid, cell_id,
625 llc_msg, llc_msg_size);
626}
627
628static void send_llc_dl_ui(
629 struct gprs_ns_inst *nsi, const char *text,
630 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
631 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
632 unsigned sapi, unsigned nu,
633 const uint8_t *msg, size_t msg_size)
634{
635 /* GPRS Network Service, PDU type: NS_UNITDATA */
636 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
637 unsigned char llc_msg[4096] = {
638 0x00, 0x00, 0x01
639 };
640
641 size_t llc_msg_size = 3 + msg_size + 3;
642 uint8_t e_bit = 0;
643 uint8_t pm_bit = 1;
644 unsigned fcs;
645
646 nu &= 0x01ff;
647
648 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
649
650 llc_msg[0] = 0x40 | (sapi & 0x0f);
651 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
652 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
653
654 memcpy(llc_msg + 3, msg, msg_size);
655
656 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
657 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
658 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
659 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
660
661 send_bssgp_dl_unitdata(nsi, text ? text : "LLC UI",
662 src_addr, nsbvci, tlli,
663 with_racap_drx, imsi, imsi_size,
664 llc_msg, llc_msg_size);
665}
666
667
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200668static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
669 uint16_t nsvci, uint16_t nsei)
670{
671 printf("Setup NS-VC: remote 0x%08x:%d, "
672 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
673 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
674 nsvci, nsvci, nsei, nsei);
675
676 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
677 send_ns_alive(nsi, src_addr);
678 send_ns_unblock(nsi, src_addr);
679 send_ns_alive_ack(nsi, src_addr);
680}
681
682static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
683 uint16_t bvci)
684{
685 printf("Setup BSSGP: remote 0x%08x:%d, "
686 "BVCI 0x%04x(%d)\n\n",
687 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
688 bvci, bvci);
689
690 send_bssgp_reset(nsi, src_addr, bvci);
691}
692
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200693static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
694{
695 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
696 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
697 send_ns_alive_ack(nsi, sgsn_peer);
698 send_ns_unblock_ack(nsi, sgsn_peer);
699 send_ns_alive(nsi, sgsn_peer);
700}
701
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200702static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
703{
704 sgsn_peer->sin_family = AF_INET;
705 sgsn_peer->sin_port = htons(32000);
706 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
707}
708
709static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
710{
711 size_t i;
712
713 for (i = 0; i < size; ++i) {
714 bss_peers[i].sin_family = AF_INET;
715 bss_peers[i].sin_port = htons((i + 1) * 1111);
716 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
717 }
718}
719
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200720int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
721 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
722
723/* override */
724int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
725 struct msgb *msg, uint16_t bvci)
726{
727 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
728 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200729 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200730
731 switch (event) {
732 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +0200733 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200734 default:
735 break;
736 }
737 return 0;
738}
739
740/* override */
741ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
742 const struct sockaddr *dest_addr, socklen_t addrlen)
743{
744 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
745 const struct sockaddr *, socklen_t);
746 static sendto_t real_sendto = NULL;
747 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200748 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200749
750 if (!real_sendto)
751 real_sendto = dlsym(RTLD_NEXT, "sendto");
752
753 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200754 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
755 dest_host, dest_port,
756 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200757 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200758 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
759 dest_host, dest_port,
760 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200761 else
762 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
763
764 return len;
765}
766
767/* override */
768int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
769{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200770 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
771 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200772 uint16_t bvci = msgb_bvci(msg);
773 uint16_t nsei = msgb_nsei(msg);
774
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200775 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200776
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200777 if (!real_gprs_ns_sendmsg)
778 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
779
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200780 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200781 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
782 "msg length %d (%s)\n",
783 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200784 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200785 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
786 "msg length %d (%s)\n",
787 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200788
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200789 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200790}
791
792static void dump_rate_ctr_group(FILE *stream, const char *prefix,
793 struct rate_ctr_group *ctrg)
794{
795 unsigned int i;
796
797 for (i = 0; i < ctrg->desc->num_ctr; i++) {
798 struct rate_ctr *ctr = &ctrg->ctr[i];
799 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
800 fprintf(stream, " %s%s: %llu%s",
801 prefix, ctrg->desc->ctr_desc[i].description,
802 (long long)ctr->current,
803 "\n");
804 };
805}
806
807/* Signal handler for signals from NS layer */
808static int test_signal(unsigned int subsys, unsigned int signal,
809 void *handler_data, void *signal_data)
810{
811 struct ns_signal_data *nssd = signal_data;
812 int rc;
813
814 if (subsys != SS_L_NS)
815 return 0;
816
817 switch (signal) {
818 case S_NS_RESET:
819 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
820 nssd->nsvc->nsvci,
821 gprs_ns_ll_str(nssd->nsvc));
822 break;
823
824 case S_NS_ALIVE_EXP:
825 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
826 nssd->nsvc->nsvci,
827 gprs_ns_ll_str(nssd->nsvc));
828 break;
829
830 case S_NS_BLOCK:
831 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
832 nssd->nsvc->nsvci,
833 gprs_ns_ll_str(nssd->nsvc));
834 break;
835
836 case S_NS_UNBLOCK:
837 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
838 nssd->nsvc->nsvci,
839 gprs_ns_ll_str(nssd->nsvc));
840 break;
841
842 case S_NS_REPLACED:
843 printf("==> got signal NS_REPLACED: 0x%04x/%s",
844 nssd->nsvc->nsvci,
845 gprs_ns_ll_str(nssd->nsvc));
846 printf(" -> 0x%04x/%s\n",
847 nssd->old_nsvc->nsvci,
848 gprs_ns_ll_str(nssd->old_nsvc));
849 break;
850
851 default:
852 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
853 nssd->nsvc->nsvci,
854 gprs_ns_ll_str(nssd->nsvc));
855 break;
856 }
857 printf("\n");
858 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
859 return rc;
860}
861
862static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
863{
864 struct msgb *msg;
865 int ret;
866 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
867 fprintf(stderr, "message too long: %d\n", data_len);
868 return -1;
869 }
870
871 msg = gprs_ns_msgb_alloc();
872 memmove(msg->data, data, data_len);
873 msg->l2h = msg->data;
874 msgb_put(msg, data_len);
875
876 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
877 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
878 osmo_hexdump(data, data_len));
879
880 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
881
882 printf("result (%s) = %d\n\n", text, ret);
883
884 msgb_free(msg);
885
886 return ret;
887}
888
889static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
890{
891 struct gprs_nsvc *nsvc;
892
893 printf("Current NS-VCIs:\n");
894 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
895 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200896 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200897 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200898 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
899 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
900 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200901 );
902 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
903 }
904 printf("\n");
905}
906
907static void test_gbproxy()
908{
909 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
910 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200911 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200912
913 bssgp_nsi = nsi;
914 gbcfg.nsi = bssgp_nsi;
915 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
916
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200917 configure_sgsn_peer(&sgsn_peer);
918 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200919
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200920 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200921 printf("--- Initialise SGSN ---\n\n");
922
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200923 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200924 gprs_dump_nsi(nsi);
925
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200926 printf("--- Initialise BSS 1 ---\n\n");
927
928 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
929 setup_bssgp(nsi, &bss_peer[0], 0x1002);
930 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200931 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200932
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200933 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
934
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200935 printf("--- Initialise BSS 2 ---\n\n");
936
937 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
938 setup_bssgp(nsi, &bss_peer[1], 0x2002);
939 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200940 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200941
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200942 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
943
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200944 printf("--- Move BSS 1 to new port ---\n\n");
945
946 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
947 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200948 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200949
950 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
951
952 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
953 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200954 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200955
956 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
957
958 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
959 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200960 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200961
962 printf("--- Move BSS 2 to new port ---\n\n");
963
964 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
965 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200966 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200967
968 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
969
970 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
971 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200972 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200973
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200974 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
975
976 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
977 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200978 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200979
980 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
981
982 setup_bssgp(nsi, &bss_peer[0], 0x1012);
983 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200984 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200985
986 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
987
988 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
989
990 setup_bssgp(nsi, &bss_peer[0], 0x1002);
991 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200992 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200993
994 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
995
996 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
997
998 setup_bssgp(nsi, &bss_peer[0], 0x1002);
999 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001000 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +02001001
1002 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1003
1004 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
1005
1006 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
1007
1008 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
1009
1010 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
1011
1012 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1013
1014 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
1015
1016 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
1017
1018 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
1019
1020 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
1021
1022 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
1023
1024 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
1025
1026 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
1027
1028 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
1029
1030 setup_bssgp(nsi, &bss_peer[2], 0x1002);
1031 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001032 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +02001033
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001034 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +02001035
Jacob Erlbeck2082afa2013-10-18 13:04:47 +02001036 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1037
1038 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1039
1040 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
1041
1042 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
1043
1044 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
1045
Jacob Erlbeckda890c72013-10-18 22:12:16 +02001046 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
1047
1048 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
1049
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001050 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +02001051
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001052 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001053 gprs_ns_destroy(nsi);
1054 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001055}
1056
1057static void test_gbproxy_ident_changes()
1058{
1059 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1060 struct sockaddr_in bss_peer[1] = {{0},};
1061 struct sockaddr_in sgsn_peer= {0};
1062 uint16_t nsei[2] = {0x1000, 0x2000};
1063 uint16_t nsvci[2] = {0x1001, 0x2001};
1064 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
1065
1066 bssgp_nsi = nsi;
1067 gbcfg.nsi = bssgp_nsi;
1068 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
1069
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001070 configure_sgsn_peer(&sgsn_peer);
1071 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001072
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001073 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001074 printf("--- Initialise SGSN ---\n\n");
1075
Jacob Erlbeck2e038f72014-07-07 10:46:00 +02001076 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001077 gprs_dump_nsi(nsi);
1078
1079 printf("--- Initialise BSS 1 ---\n\n");
1080
1081 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
1082 gprs_dump_nsi(nsi);
1083
1084 printf("--- Setup BVCI 1 ---\n\n");
1085
1086 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1087 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001088 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001089
1090 printf("--- Setup BVCI 2 ---\n\n");
1091
1092 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
1093 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001094 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001095
1096 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1097
1098 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1099 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1100
1101 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
1102
1103 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
1104 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
1105
1106 printf("--- Change NSEI ---\n\n");
1107
1108 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
1109 gprs_dump_nsi(nsi);
1110
1111 printf("--- Setup BVCI 1 ---\n\n");
1112
1113 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1114 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001115 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001116
1117 printf("--- Setup BVCI 3 ---\n\n");
1118
1119 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
1120 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001121 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001122
1123 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1124
1125 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1126 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1127
1128 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1129 " (should fail) ---\n\n");
1130
1131 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001132 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001133 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001134 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001135
1136 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1137
1138 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1139 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1140
1141 printf("--- Change NSVCI ---\n\n");
1142
1143 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
1144 gprs_dump_nsi(nsi);
1145
1146 printf("--- Setup BVCI 1 ---\n\n");
1147
1148 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1149 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001150 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001151
1152 printf("--- Setup BVCI 4 ---\n\n");
1153
1154 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
1155 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001156 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001157
1158 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1159
1160 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1161 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1162
1163 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1164 " (should fail) ---\n\n");
1165
1166 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001167 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001168 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001169 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001170
1171 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1172
1173 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1174 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1175
1176 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
1177
1178 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
1179 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
1180
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001181 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001182 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001183
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001184 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001185 gprs_ns_destroy(nsi);
1186 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001187}
1188
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001189static void test_gbproxy_ra_patching()
1190{
1191 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1192 struct sockaddr_in bss_peer[1] = {{0},};
1193 struct sockaddr_in sgsn_peer= {0};
1194 struct gprs_ra_id rai_bss =
1195 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1196 struct gprs_ra_id rai_sgsn =
1197 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
1198 struct gprs_ra_id rai_unknown =
1199 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001200 uint16_t cell_id = 0x7530;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001201 const char *err_msg = NULL;
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001202 const uint32_t ptmsi = 0xefe2b700;
1203 const uint32_t local_tlli = 0xefe2b700;
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001204 const uint32_t foreign_tlli = 0xbbc54679;
1205 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001206 struct gbproxy_tlli_info *tlli_info;
1207 struct gbproxy_peer *peer;
1208
1209 OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001210
1211 bssgp_nsi = nsi;
1212 gbcfg.nsi = bssgp_nsi;
1213 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +02001214 gbcfg.core_mcc = 123;
1215 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +02001216 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +02001217 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001218 gbcfg.patch_ptmsi = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001219
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001220 configure_sgsn_peer(&sgsn_peer);
1221 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001222
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001223 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001224 if (gbproxy_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001225 fprintf(stderr, "Failed to compile RE '%s': %s\n",
1226 gbcfg.match_re, err_msg);
1227 exit(1);
1228 }
1229
1230
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001231 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001232 printf("--- Initialise SGSN ---\n\n");
1233
1234 connect_sgsn(nsi, &sgsn_peer);
1235 gprs_dump_nsi(nsi);
1236
1237 printf("--- Initialise BSS 1 ---\n\n");
1238
1239 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1240 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1241 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001242 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001243
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +02001244 peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001245 OSMO_ASSERT(peer != NULL);
1246
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001247 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1248
Jacob Erlbeck299389a2014-08-21 16:34:18 +02001249 send_bssgp_suspend(nsi, &bss_peer[0], 0xccd1758b, &rai_bss);
1250 send_bssgp_suspend_ack(nsi, &sgsn_peer, 0xccd1758b, &rai_sgsn);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001251
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001252 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001253 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001254
1255 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1256
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001257 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1258 foreign_tlli, &rai_bss, cell_id,
1259 GPRS_SAPI_GMM, 0,
1260 dtap_attach_req, sizeof(dtap_attach_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001261
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001262 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1263 foreign_tlli, 0, NULL, 0,
1264 GPRS_SAPI_GMM, 0,
1265 dtap_identity_req, sizeof(dtap_identity_req));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001266
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001267 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1268 foreign_tlli, &rai_bss, cell_id,
1269 GPRS_SAPI_GMM, 3,
1270 dtap_identity_resp, sizeof(dtap_identity_resp));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001271
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001272 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1273 foreign_tlli, 1, imsi, sizeof(imsi),
1274 GPRS_SAPI_GMM, 1,
1275 dtap_attach_acc, sizeof(dtap_attach_acc));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001276
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001277 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001278 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001279 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1280 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1281 OSMO_ASSERT(!tlli_info->tlli.bss_validated);
1282 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1283 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1284 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1285 OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
1286 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001287
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001288 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1289 local_tlli, &rai_bss, cell_id,
1290 GPRS_SAPI_GMM, 4,
1291 dtap_attach_complete, sizeof(dtap_attach_complete));
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001292
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001293 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001294 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001295 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1296 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1297 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1298 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1299 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1300 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1301 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1302 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001303
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001304 /* Replace APN (1) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001305 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1306 local_tlli, &rai_bss, cell_id,
1307 GPRS_SAPI_GMM, 3,
1308 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001309
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001310 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001311 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001312 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1313 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1314 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1315 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1316 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1317 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1318 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1319 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001320
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001321 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1322 local_tlli, 1, imsi, sizeof(imsi),
1323 GPRS_SAPI_GMM, 2,
1324 dtap_gmm_information, sizeof(dtap_gmm_information));
Jacob Erlbeck11669742014-06-06 18:47:36 +02001325
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001326 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001327 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001328 OSMO_ASSERT(tlli_info->tlli.assigned == 0);
1329 OSMO_ASSERT(tlli_info->tlli.current == local_tlli);
1330 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
1331 OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001332
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001333 /* Replace APN (2) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001334 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1335 local_tlli, &rai_bss, cell_id,
1336 GPRS_SAPI_GMM, 3,
1337 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001338
Jacob Erlbeck73685282014-05-23 20:48:07 +02001339 gbcfg.core_apn[0] = 0;
1340 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001341
1342 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001343 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1344 local_tlli, &rai_bss, cell_id,
1345 GPRS_SAPI_GMM, 3,
1346 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001347
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001348 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001349
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001350 /* Detach */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001351 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1352 local_tlli, &rai_bss, cell_id,
1353 GPRS_SAPI_GMM, 6,
1354 dtap_detach_req, sizeof(dtap_detach_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001355
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001356 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1357 local_tlli, 1, imsi, sizeof(imsi),
1358 GPRS_SAPI_GMM, 5,
1359 dtap_detach_acc, sizeof(dtap_detach_acc));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001360
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001361 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001362
1363 printf("--- RA update ---\n\n");
1364
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001365 send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1366 foreign_tlli, &rai_bss, 0x7080,
1367 GPRS_SAPI_GMM, 5,
1368 dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001369
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001370 send_llc_dl_ui(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1371 foreign_tlli, 1, imsi, sizeof(imsi),
1372 GPRS_SAPI_GMM, 6,
1373 dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001374
1375 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001376 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1377 local_tlli, &rai_bss, cell_id,
1378 GPRS_SAPI_GMM, 3,
1379 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001380
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001381 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001382
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +02001383 /* Detach (power off -> no Detach Accept) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001384 send_llc_ul_ui(nsi, "DETACH REQ (PWR OFF)", &bss_peer[0], 0x1002,
1385 local_tlli, &rai_bss, cell_id,
1386 GPRS_SAPI_GMM, 6,
1387 dtap_detach_po_req, sizeof(dtap_detach_po_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001388
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001389 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001390 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001391
1392 printf("--- Bad cases ---\n\n");
1393
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001394 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001395 send_llc_ul_ui(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1396 local_tlli, &rai_bss, cell_id,
1397 GPRS_SAPI_GMM, 3,
1398 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001399
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001400 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck299389a2014-08-21 16:34:18 +02001401 send_bssgp_suspend_ack(nsi, &sgsn_peer, 0xccd1758b, &rai_unknown);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001402
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001403 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001404 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001405
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02001406 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001407 gprs_ns_destroy(nsi);
1408 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001409}
1410
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001411static void test_gbproxy_ptmsi_patching()
1412{
1413 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1414 struct sockaddr_in bss_peer[1] = {{0},};
1415 struct sockaddr_in sgsn_peer= {0};
1416 struct gprs_ra_id rai_bss =
1417 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1418 struct gprs_ra_id rai_sgsn =
1419 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
Jacob Erlbeck299389a2014-08-21 16:34:18 +02001420 struct gprs_ra_id rai_wrong_mcc_sgsn =
1421 {.mcc = 999, .mnc = 456, .lac = 16464, .rac = 96};
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001422 struct gprs_ra_id rai_unknown =
1423 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
1424 uint16_t cell_id = 0x1234;
1425
1426 const uint32_t sgsn_ptmsi = 0xefe2b700;
1427 const uint32_t local_sgsn_tlli = 0xefe2b700;
1428 const uint32_t random_sgsn_tlli = 0x7c69fb81;
1429
1430 const uint32_t bss_ptmsi = 0xc00f7304;
1431 const uint32_t local_bss_tlli = 0xc00f7304;
1432 const uint32_t foreign_bss_tlli = 0x8000dead;
1433
1434 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
1435 struct gbproxy_tlli_info *tlli_info;
1436 struct gbproxy_peer *peer;
1437 unsigned bss_nu = 0;
1438 unsigned sgsn_nu = 0;
1439
1440 OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
1441
1442 bssgp_nsi = nsi;
1443 gbcfg.nsi = bssgp_nsi;
1444 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
1445 gbcfg.core_mcc = 123;
1446 gbcfg.core_mnc = 456;
1447 gbcfg.core_apn = talloc_zero_size(NULL, 100);
1448 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
1449 gbcfg.patch_ptmsi = 1;
1450 gbcfg.bss_ptmsi_state = 0;
1451 gbcfg.sgsn_tlli_state = 1;
1452
1453 configure_sgsn_peer(&sgsn_peer);
1454 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
1455
1456 printf("=== %s ===\n", __func__);
1457 printf("--- Initialise SGSN ---\n\n");
1458
1459 connect_sgsn(nsi, &sgsn_peer);
1460
1461 printf("--- Initialise BSS 1 ---\n\n");
1462
1463 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1464 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1465
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +02001466 peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001467 OSMO_ASSERT(peer != NULL);
1468
1469 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1470
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001471 gprs_dump_nsi(nsi);
1472 dump_global(stdout, 0);
1473 dump_peers(stdout, 0, 0, &gbcfg);
1474
1475 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1476
1477 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1478 foreign_bss_tlli, &rai_unknown, cell_id,
1479 GPRS_SAPI_GMM, bss_nu++,
1480 dtap_attach_req, sizeof(dtap_attach_req));
1481
1482 dump_peers(stdout, 0, 0, &gbcfg);
1483
1484 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1485 random_sgsn_tlli, 0, NULL, 0,
1486 GPRS_SAPI_GMM, sgsn_nu++,
1487 dtap_identity_req, sizeof(dtap_identity_req));
1488
1489 dump_peers(stdout, 0, 0, &gbcfg);
1490
1491 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1492 foreign_bss_tlli, &rai_bss, cell_id,
1493 GPRS_SAPI_GMM, bss_nu++,
1494 dtap_identity_resp, sizeof(dtap_identity_resp));
1495
1496 dump_peers(stdout, 0, 0, &gbcfg);
1497
1498 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1499 random_sgsn_tlli, 1, imsi, sizeof(imsi),
1500 GPRS_SAPI_GMM, sgsn_nu++,
1501 dtap_attach_acc, sizeof(dtap_attach_acc));
1502
1503 dump_peers(stdout, 0, 0, &gbcfg);
1504
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001505 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, random_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001506 OSMO_ASSERT(tlli_info);
1507 OSMO_ASSERT(tlli_info->tlli.assigned == local_bss_tlli);
1508 OSMO_ASSERT(tlli_info->tlli.current == foreign_bss_tlli);
1509 OSMO_ASSERT(!tlli_info->tlli.bss_validated);
1510 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1511 OSMO_ASSERT(tlli_info->tlli.ptmsi == bss_ptmsi);
1512 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_sgsn_tlli);
1513 OSMO_ASSERT(tlli_info->sgsn_tlli.current == random_sgsn_tlli);
1514 OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
1515 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
1516 OSMO_ASSERT(tlli_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
1517
1518 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1519 local_bss_tlli, &rai_bss, cell_id,
1520 GPRS_SAPI_GMM, bss_nu++,
1521 dtap_attach_complete, sizeof(dtap_attach_complete));
1522
1523 dump_peers(stdout, 0, 0, &gbcfg);
1524
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001525 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001526 OSMO_ASSERT(tlli_info);
1527 OSMO_ASSERT(tlli_info->tlli.assigned == local_bss_tlli);
1528 OSMO_ASSERT(tlli_info->tlli.current == foreign_bss_tlli);
1529 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1530 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1531 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_sgsn_tlli);
1532 OSMO_ASSERT(tlli_info->sgsn_tlli.current == random_sgsn_tlli);
1533 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1534 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
1535
1536 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1537 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1538 GPRS_SAPI_GMM, sgsn_nu++,
1539 dtap_gmm_information, sizeof(dtap_gmm_information));
1540
1541 dump_peers(stdout, 0, 0, &gbcfg);
1542
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001543 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001544 OSMO_ASSERT(tlli_info);
1545 OSMO_ASSERT(tlli_info->tlli.current == local_bss_tlli);
1546 OSMO_ASSERT(tlli_info->tlli.assigned == 0);
1547 OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_sgsn_tlli);
1548 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
1549
1550 /* Non-DTAP */
1551 send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
1552 local_bss_tlli, &rai_bss, cell_id,
1553 llc_u_xid_ul, sizeof(llc_u_xid_ul));
1554
1555 send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer, 0x1002,
1556 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1557 llc_u_xid_dl, sizeof(llc_u_xid_dl));
1558
1559 send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
1560 local_bss_tlli, &rai_bss, cell_id,
1561 llc_ui_ll11_dns_query_ul,
1562 sizeof(llc_ui_ll11_dns_query_ul));
1563
1564 send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer, 0x1002,
1565 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1566 llc_ui_ll11_dns_resp_dl,
1567 sizeof(llc_ui_ll11_dns_resp_dl));
1568
1569 dump_peers(stdout, 0, 0, &gbcfg);
1570
Jacob Erlbeck299389a2014-08-21 16:34:18 +02001571 /* Other messages */
1572 send_bssgp_llc_discarded(nsi, &bss_peer[0], 0x1002,
1573 local_bss_tlli, 1, 12);
1574
1575 dump_peers(stdout, 0, 0, &gbcfg);
1576
1577 send_bssgp_suspend(nsi, &bss_peer[0], local_bss_tlli, &rai_bss);
1578
1579 dump_peers(stdout, 0, 0, &gbcfg);
1580
1581 send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli, &rai_sgsn);
1582
1583 dump_peers(stdout, 0, 0, &gbcfg);
1584
1585 /* Bad case: Invalid BVCI */
1586 send_bssgp_llc_discarded(nsi, &bss_peer[0], 0xeee1,
1587 local_bss_tlli, 1, 12);
1588 dump_global(stdout, 0);
1589
1590 /* Bad case: Invalid RAI */
1591 send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli, &rai_unknown);
1592
1593 dump_global(stdout, 0);
1594
1595 /* Bad case: Invalid MCC (LAC ok) */
1596 send_bssgp_suspend_ack(nsi, &sgsn_peer, local_sgsn_tlli,
1597 &rai_wrong_mcc_sgsn);
1598
1599 dump_global(stdout, 0);
1600
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001601 /* Detach */
1602 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1603 local_bss_tlli, &rai_bss, cell_id,
1604 GPRS_SAPI_GMM, bss_nu++,
1605 dtap_detach_req, sizeof(dtap_detach_req));
1606
1607 dump_peers(stdout, 0, 0, &gbcfg);
1608
1609 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1610 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1611 GPRS_SAPI_GMM, sgsn_nu++,
1612 dtap_detach_acc, sizeof(dtap_detach_acc));
1613
1614 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck299389a2014-08-21 16:34:18 +02001615
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001616 dump_global(stdout, 0);
1617
1618 gbprox_reset(&gbcfg);
1619 gprs_ns_destroy(nsi);
1620 nsi = NULL;
1621}
1622
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001623/* TODO: Move tlv testing to libosmocore */
1624int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1625int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1626 uint8_t **value);
1627int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1628 size_t *value_len);
1629int lv_shift(uint8_t **data, size_t *data_len,
1630 uint8_t **value, size_t *value_len);
1631
1632static void check_tlv_match(uint8_t **data, size_t *data_len,
1633 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1634{
1635 uint8_t *value;
1636 size_t value_len;
1637 int rc;
1638
1639 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1640 OSMO_ASSERT(rc == 0);
1641
1642 rc = tlv_match(data, data_len, tag, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001643 OSMO_ASSERT(rc == (int)value_len + 2);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001644 OSMO_ASSERT(value_len == exp_len);
1645 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1646}
1647
1648static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1649 uint8_t tag, size_t len, const uint8_t *exp_val)
1650{
1651 uint8_t *value;
1652 int rc;
1653
1654 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1655 OSMO_ASSERT(rc == 0);
1656
1657 rc = tv_fixed_match(data, data_len, tag, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001658 OSMO_ASSERT(rc == (int)len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001659 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1660}
1661
1662static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1663 size_t len, const uint8_t *exp_val)
1664{
1665 uint8_t *value;
1666 int rc;
1667
1668 rc = v_fixed_shift(data, data_len, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001669 OSMO_ASSERT(rc == (int)len);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001670 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1671}
1672
1673static void check_lv_shift(uint8_t **data, size_t *data_len,
1674 size_t exp_len, const uint8_t *exp_val)
1675{
1676 uint8_t *value;
1677 size_t value_len;
1678 int rc;
1679
1680 rc = lv_shift(data, data_len, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001681 OSMO_ASSERT(rc == (int)value_len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001682 OSMO_ASSERT(value_len == exp_len);
1683 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1684}
1685
1686static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1687 const uint8_t *test_data)
1688{
1689 uint8_t buf[300] = {0};
1690
1691 uint8_t *unchanged_ptr = buf - 1;
1692 size_t unchanged_len = 0xdead;
1693 size_t tmp_data_len = data_len;
1694 uint8_t *value = unchanged_ptr;
1695 size_t value_len = unchanged_len;
1696 uint8_t *data = buf;
1697
1698 OSMO_ASSERT(data_len <= sizeof(buf));
1699
1700 tlv_put(data, tag, len, test_data);
1701 if (data_len < len + 2) {
1702 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1703 tag, &value, &value_len));
1704 OSMO_ASSERT(tmp_data_len == 0);
1705 OSMO_ASSERT(data == buf + data_len);
1706 OSMO_ASSERT(value == unchanged_ptr);
1707 OSMO_ASSERT(value_len == unchanged_len);
1708 } else {
1709 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1710 tag, &value, &value_len));
1711 OSMO_ASSERT(value != unchanged_ptr);
1712 OSMO_ASSERT(value_len != unchanged_len);
1713 }
1714}
1715
1716static void check_tv_fixed_match_data_len(size_t data_len,
1717 uint8_t tag, size_t len,
1718 const uint8_t *test_data)
1719{
1720 uint8_t buf[300] = {0};
1721
1722 uint8_t *unchanged_ptr = buf - 1;
1723 size_t tmp_data_len = data_len;
1724 uint8_t *value = unchanged_ptr;
1725 uint8_t *data = buf;
1726
1727 OSMO_ASSERT(data_len <= sizeof(buf));
1728
1729 tv_fixed_put(data, tag, len, test_data);
1730
1731 if (data_len < len + 1) {
1732 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1733 tag, len, &value));
1734 OSMO_ASSERT(tmp_data_len == 0);
1735 OSMO_ASSERT(data == buf + data_len);
1736 OSMO_ASSERT(value == unchanged_ptr);
1737 } else {
1738 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1739 tag, len, &value));
1740 OSMO_ASSERT(value != unchanged_ptr);
1741 }
1742}
1743
1744static void check_v_fixed_shift_data_len(size_t data_len,
1745 size_t len, const uint8_t *test_data)
1746{
1747 uint8_t buf[300] = {0};
1748
1749 uint8_t *unchanged_ptr = buf - 1;
1750 size_t tmp_data_len = data_len;
1751 uint8_t *value = unchanged_ptr;
1752 uint8_t *data = buf;
1753
1754 OSMO_ASSERT(data_len <= sizeof(buf));
1755
1756 memcpy(data, test_data, len);
1757
1758 if (data_len < len) {
1759 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1760 len, &value));
1761 OSMO_ASSERT(tmp_data_len == 0);
1762 OSMO_ASSERT(data == buf + data_len);
1763 OSMO_ASSERT(value == unchanged_ptr);
1764 } else {
1765 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1766 len, &value));
1767 OSMO_ASSERT(value != unchanged_ptr);
1768 }
1769}
1770
1771static void check_lv_shift_data_len(size_t data_len,
1772 size_t len, const uint8_t *test_data)
1773{
1774 uint8_t buf[300] = {0};
1775
1776 uint8_t *unchanged_ptr = buf - 1;
1777 size_t unchanged_len = 0xdead;
1778 size_t tmp_data_len = data_len;
1779 uint8_t *value = unchanged_ptr;
1780 size_t value_len = unchanged_len;
1781 uint8_t *data = buf;
1782
1783 lv_put(data, len, test_data);
1784 if (data_len < len + 1) {
1785 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1786 &value, &value_len));
1787 OSMO_ASSERT(tmp_data_len == 0);
1788 OSMO_ASSERT(data == buf + data_len);
1789 OSMO_ASSERT(value == unchanged_ptr);
1790 OSMO_ASSERT(value_len == unchanged_len);
1791 } else {
1792 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1793 &value, &value_len));
1794 OSMO_ASSERT(value != unchanged_ptr);
1795 OSMO_ASSERT(value_len != unchanged_len);
1796 }
1797}
1798
1799static void test_tlv_shift_functions()
1800{
1801 uint8_t test_data[1024];
1802 uint8_t buf[1024];
1803 uint8_t *data_end;
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001804 unsigned i, len;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001805 uint8_t *data;
1806 size_t data_len;
1807 const uint8_t tag = 0x1a;
1808
1809 printf("Test shift functions\n");
1810
1811 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1812 test_data[i] = (uint8_t)i;
1813
1814 for (len = 0; len < 256; len++) {
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001815 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001816
1817 memset(buf, 0xee, sizeof(buf));
1818 data_end = data = buf;
1819
1820 for (i = 0; i < iterations; i++) {
1821 data_end = tlv_put(data_end, tag, len, test_data);
1822 data_end = tv_fixed_put(data_end, tag, len, test_data);
1823 /* v_fixed_put */
1824 memcpy(data_end, test_data, len);
1825 data_end += len;
1826 data_end = lv_put(data_end, len, test_data);
1827 }
1828
1829 data_len = data_end - data;
1830 OSMO_ASSERT(data_len <= sizeof(buf));
1831
1832 for (i = 0; i < iterations; i++) {
1833 check_tlv_match(&data, &data_len, tag, len, test_data);
1834 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1835 check_v_fixed_shift(&data, &data_len, len, test_data);
1836 check_lv_shift(&data, &data_len, len, test_data);
1837 }
1838
1839 OSMO_ASSERT(data == data_end);
1840
1841 /* Test at end of data */
1842
1843 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1844 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1845 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1846 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1847
1848 /* Test invalid data_len */
1849 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1850 check_tlv_match_data_len(data_len, tag, len, test_data);
1851 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1852 check_v_fixed_shift_data_len(data_len, len, test_data);
1853 check_lv_shift_data_len(data_len, len, test_data);
1854 }
1855 }
1856}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001857
1858static void test_gbproxy_tlli_expire(void)
1859{
1860 struct gbproxy_config cfg = {0};
1861 struct gbproxy_peer *peer;
1862 const char *err_msg = NULL;
1863 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1864 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001865 const uint8_t imsi3[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0x76, 0xf8 };
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001866 const uint32_t tlli1 = 1234 | 0xc0000000;
1867 const uint32_t tlli2 = 5678 | 0xc0000000;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001868 const uint32_t tlli3 = 3456 | 0xc0000000;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001869 const char *filter_re = ".*";
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001870 time_t now = 1407479214;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001871
1872 printf("Test TLLI info expiry\n\n");
1873
1874 gbproxy_init_config(&cfg);
1875
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001876 if (gbproxy_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001877 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1878 err_msg);
1879 OSMO_ASSERT(err_msg == NULL);
1880 }
1881
1882 {
1883 struct gbproxy_tlli_info *tlli_info;
1884
1885 printf("Test TLLI replacement:\n");
1886
1887 cfg.tlli_max_len = 0;
1888 cfg.tlli_max_age = 0;
1889 peer = gbproxy_peer_alloc(&cfg, 20);
1890 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1891
1892 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001893 tlli_info = gbproxy_register_tlli(peer, tlli1,
1894 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001895 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001896 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001897 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1898
1899 /* replace the old entry */
1900 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001901 tlli_info = gbproxy_register_tlli(peer, tlli2,
1902 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001903 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001904 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001905 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1906
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001907 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001908
1909 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001910 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001911 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001912 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001913 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001914 OSMO_ASSERT(!tlli_info);
1915
1916 printf("\n");
1917
1918 gbproxy_peer_free(peer);
1919 }
1920
1921 {
1922 struct gbproxy_tlli_info *tlli_info;
1923
1924 printf("Test IMSI replacement:\n");
1925
1926 cfg.tlli_max_len = 0;
1927 cfg.tlli_max_age = 0;
1928 peer = gbproxy_peer_alloc(&cfg, 20);
1929 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1930
1931 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001932 tlli_info = gbproxy_register_tlli(peer, tlli1,
1933 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001934 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001935 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001936 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1937
1938 /* try to replace the old entry */
1939 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001940 tlli_info = gbproxy_register_tlli(peer, tlli1,
1941 imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001942 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001943 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001944 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1945
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001946 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001947
1948 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001949 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001950 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001951 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001952 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001953 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001954
1955 printf("\n");
1956
1957 gbproxy_peer_free(peer);
1958 }
1959
1960 {
1961 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001962 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001963
1964 printf("Test TLLI expiry, max_len == 1:\n");
1965
1966 cfg.tlli_max_len = 1;
1967 cfg.tlli_max_age = 0;
1968 peer = gbproxy_peer_alloc(&cfg, 20);
1969 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1970
1971 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001972 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001973 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1974
1975 /* replace the old entry */
1976 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001977 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001978 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1979
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001980 num_removed = gbproxy_remove_stale_tllis(peer, time(NULL) + 2);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001981 OSMO_ASSERT(num_removed == 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001982 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1983
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001984 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001985
1986 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001987 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001988 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001989 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001990 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001991 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001992
1993 printf("\n");
1994
1995 gbproxy_peer_free(peer);
1996 }
1997
1998 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001999 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02002000 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002001
2002 printf("Test TLLI expiry, max_age == 1:\n");
2003
2004 cfg.tlli_max_len = 0;
2005 cfg.tlli_max_age = 1;
2006 peer = gbproxy_peer_alloc(&cfg, 20);
2007 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
2008
2009 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002010 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002011 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
2012
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002013 printf(" Add TLLI 2, IMSI 2 (should not expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002014 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002015 now + 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002016 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
2017
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002018 num_removed = gbproxy_remove_stale_tllis(peer, now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002019 OSMO_ASSERT(num_removed == 1);
2020 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
2021
2022 dump_peers(stdout, 2, now + 2, &cfg);
2023
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002024 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002025 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002026 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002027 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002028 OSMO_ASSERT(tlli_info);
2029 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
2030
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002031 printf("\n");
2032
2033 gbproxy_peer_free(peer);
2034 }
2035
2036 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002037 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002038 int num_removed;
2039
2040 printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
2041
2042 cfg.tlli_max_len = 0;
2043 cfg.tlli_max_age = 1;
2044 peer = gbproxy_peer_alloc(&cfg, 20);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002045 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
2046
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002047 printf(" Add TLLI 1, IMSI 1 (should expire)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002048 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002049 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
2050
2051 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002052 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002053 now + 1);
2054 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
2055
2056 printf(" Add TLLI 3, IMSI 3 (should not expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002057 gbproxy_register_tlli(peer, tlli3, imsi3, ARRAY_SIZE(imsi3),
2058 now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002059 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 3);
2060
2061 dump_peers(stdout, 2, now + 2, &cfg);
2062
2063 printf(" Remove stale TLLIs\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002064 num_removed = gbproxy_remove_stale_tllis(peer, now + 3);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02002065 OSMO_ASSERT(num_removed == 2);
2066 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
2067
2068 dump_peers(stdout, 2, now + 2, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002069
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002070 /* verify that tlli3 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002071 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002072 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002073 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002074 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002075 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi3, ARRAY_SIZE(imsi3));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002076 OSMO_ASSERT(tlli_info);
2077 OSMO_ASSERT(tlli_info->tlli.current == tlli3);
2078
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002079 printf("\n");
2080
2081 gbproxy_peer_free(peer);
2082 }
2083}
2084
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002085static void test_gbproxy_imsi_matching(void)
2086{
2087 struct gbproxy_config cfg = {0};
2088 struct gbproxy_peer *peer;
2089 const char *err_msg = NULL;
2090 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
2091 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
2092 const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
2093 const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
2094 const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
2095 const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
2096 const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
2097 const char *filter_re1 = ".*";
2098 const char *filter_re2 = "^1234";
2099 const char *filter_re3 = "^4321";
2100 const char *filter_re4_bad = "^12[";
2101
2102 printf("=== Test IMSI/TMSI matching ===\n\n");
2103
2104 gbproxy_init_config(&cfg);
2105 OSMO_ASSERT(cfg.check_imsi == 0);
2106
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002107 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002108 OSMO_ASSERT(cfg.check_imsi == 1);
2109
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002110 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002111 OSMO_ASSERT(cfg.check_imsi == 1);
2112
2113 err_msg = NULL;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002114 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002115 OSMO_ASSERT(err_msg != NULL);
2116 OSMO_ASSERT(cfg.check_imsi == 0);
2117
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002118 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002119 OSMO_ASSERT(cfg.check_imsi == 1);
2120
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002121 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, NULL, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002122 OSMO_ASSERT(cfg.check_imsi == 0);
2123
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002124 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck29805da2014-08-14 08:57:04 +02002125 OSMO_ASSERT(cfg.check_imsi == 1);
2126
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002127 gbproxy_clear_patch_filter(&cfg);
Jacob Erlbeck29805da2014-08-14 08:57:04 +02002128 OSMO_ASSERT(cfg.check_imsi == 0);
2129
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002130 peer = gbproxy_peer_alloc(&cfg, 20);
2131
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002132 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002133 OSMO_ASSERT(cfg.check_imsi == 1);
2134
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002135 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
2136 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002137 /* imsi3_bad contains 0xE and 0xF digits, but the conversion function
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002138 * doesn't complain, so gbproxy_check_imsi() doesn't return -1 in this
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002139 * case. */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002140 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
2141 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
2142 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
2143 OSMO_ASSERT(gbproxy_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
2144 OSMO_ASSERT(gbproxy_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002145
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002146 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002147 OSMO_ASSERT(cfg.check_imsi == 1);
2148
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002149 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
2150 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
2151 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
2152 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
2153 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
2154 OSMO_ASSERT(gbproxy_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
2155 OSMO_ASSERT(gbproxy_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002156
2157 /* TODO: Check correct length but wrong type with is_mi_tmsi */
2158
2159 gbproxy_peer_free(peer);
2160}
2161
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002162static struct log_info_cat gprs_categories[] = {
2163 [DGPRS] = {
2164 .name = "DGPRS",
2165 .description = "GPRS Packet Service",
2166 .enabled = 1, .loglevel = LOGL_DEBUG,
2167 },
2168 [DNS] = {
2169 .name = "DNS",
2170 .description = "GPRS Network Service (NS)",
2171 .enabled = 1, .loglevel = LOGL_INFO,
2172 },
2173 [DBSSGP] = {
2174 .name = "DBSSGP",
2175 .description = "GPRS BSS Gateway Protocol (BSSGP)",
2176 .enabled = 1, .loglevel = LOGL_DEBUG,
2177 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002178};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002179
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002180static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002181 .cat = gprs_categories,
2182 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002183};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002184
2185int main(int argc, char **argv)
2186{
2187 osmo_init_logging(&info);
2188 log_set_use_color(osmo_stderr_target, 0);
2189 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece62772014-08-04 15:42:36 +02002190 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002191
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002192 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002193 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
2194 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002195
2196 rate_ctr_init(NULL);
2197
2198 setlinebuf(stdout);
2199
2200 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02002201 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02002202 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002203 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002204 test_gbproxy_ident_changes();
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002205 test_gbproxy_imsi_matching();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02002206 test_gbproxy_ra_patching();
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02002207 test_gbproxy_ptmsi_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002208 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002209 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002210
2211 exit(EXIT_SUCCESS);
2212}