blob: a8a84af842736b2059de549c5286c8c50f91d4cc [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,
525 struct gprs_ra_id *raid)
526{
527 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */
528 unsigned char msg[15] = {
529 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
530 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60
531 };
532
533 gsm48_construct_ra(msg + 9, raid);
534
535 send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg));
536}
537
538static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi,
539 struct sockaddr_in *src_addr,
540 struct gprs_ra_id *raid)
541{
542 /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */
543 unsigned char msg[18] = {
544 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b,
545 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d,
546 0x81, 0x01
547 };
548
549 gsm48_construct_ra(msg + 9, raid);
550
551 send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg));
552}
553
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +0200554static void send_llc_ul_ui(
555 struct gprs_ns_inst *nsi, const char *text,
556 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
557 struct gprs_ra_id *raid, uint16_t cell_id,
558 unsigned sapi, unsigned nu,
559 const uint8_t *msg, size_t msg_size)
560{
561 unsigned char llc_msg[4096] = {
562 0x00, 0xc0, 0x01
563 };
564
565 size_t llc_msg_size = 3 + msg_size + 3;
566 uint8_t e_bit = 0;
567 uint8_t pm_bit = 1;
568 unsigned fcs;
569
570 nu &= 0x01ff;
571
572 OSMO_ASSERT(llc_msg_size <= sizeof(llc_msg));
573
574 llc_msg[0] = (sapi & 0x0f);
575 llc_msg[1] = 0xc0 | (nu >> 6); /* UI frame */
576 llc_msg[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
577
578 memcpy(llc_msg + 3, msg, msg_size);
579
580 fcs = gprs_llc_fcs(llc_msg, msg_size + 3);
581 llc_msg[3 + msg_size + 0] = (uint8_t)(fcs >> 0);
582 llc_msg[3 + msg_size + 1] = (uint8_t)(fcs >> 8);
583 llc_msg[3 + msg_size + 2] = (uint8_t)(fcs >> 16);
584
585 send_bssgp_ul_unitdata(nsi, text ? text : "LLC UI",
586 src_addr, nsbvci, tlli, raid, cell_id,
587 llc_msg, llc_msg_size);
588}
589
590static void send_llc_dl_ui(
591 struct gprs_ns_inst *nsi, const char *text,
592 struct sockaddr_in *src_addr, uint16_t nsbvci, uint32_t tlli,
593 int with_racap_drx, const uint8_t *imsi, size_t imsi_size,
594 unsigned sapi, unsigned nu,
595 const uint8_t *msg, size_t msg_size)
596{
597 /* GPRS Network Service, PDU type: NS_UNITDATA */
598 /* Base Station Subsystem GPRS Protocol: UL_UNITDATA */
599 unsigned char llc_msg[4096] = {
600 0x00, 0x00, 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] = 0x40 | (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_dl_unitdata(nsi, text ? text : "LLC UI",
624 src_addr, nsbvci, tlli,
625 with_racap_drx, imsi, imsi_size,
626 llc_msg, llc_msg_size);
627}
628
629
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200630static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
631 uint16_t nsvci, uint16_t nsei)
632{
633 printf("Setup NS-VC: remote 0x%08x:%d, "
634 "NSVCI 0x%04x(%d), NSEI 0x%04x(%d)\n\n",
635 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
636 nsvci, nsvci, nsei, nsei);
637
638 send_ns_reset(nsi, src_addr, NS_CAUSE_OM_INTERVENTION, nsvci, nsei);
639 send_ns_alive(nsi, src_addr);
640 send_ns_unblock(nsi, src_addr);
641 send_ns_alive_ack(nsi, src_addr);
642}
643
644static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
645 uint16_t bvci)
646{
647 printf("Setup BSSGP: remote 0x%08x:%d, "
648 "BVCI 0x%04x(%d)\n\n",
649 ntohl(src_addr->sin_addr.s_addr), ntohs(src_addr->sin_port),
650 bvci, bvci);
651
652 send_bssgp_reset(nsi, src_addr, bvci);
653}
654
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200655static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer)
656{
657 gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
658 send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
659 send_ns_alive_ack(nsi, sgsn_peer);
660 send_ns_unblock_ack(nsi, sgsn_peer);
661 send_ns_alive(nsi, sgsn_peer);
662}
663
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200664static void configure_sgsn_peer(struct sockaddr_in *sgsn_peer)
665{
666 sgsn_peer->sin_family = AF_INET;
667 sgsn_peer->sin_port = htons(32000);
668 sgsn_peer->sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
669}
670
671static void configure_bss_peers(struct sockaddr_in *bss_peers, size_t size)
672{
673 size_t i;
674
675 for (i = 0; i < size; ++i) {
676 bss_peers[i].sin_family = AF_INET;
677 bss_peers[i].sin_port = htons((i + 1) * 1111);
678 bss_peers[i].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
679 }
680}
681
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200682int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
683 struct sockaddr_in *saddr, enum gprs_ns_ll ll);
684
685/* override */
686int gprs_ns_callback(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
687 struct msgb *msg, uint16_t bvci)
688{
689 printf("CALLBACK, event %d, msg length %d, bvci 0x%04x\n%s\n\n",
690 event, msgb_bssgp_len(msg), bvci,
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200691 osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200692
693 switch (event) {
694 case GPRS_NS_EVT_UNIT_DATA:
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200695 return gbprox_rcvmsg(&gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200696 default:
697 break;
698 }
699 return 0;
700}
701
702/* override */
703ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
704 const struct sockaddr *dest_addr, socklen_t addrlen)
705{
706 typedef ssize_t (*sendto_t)(int, const void *, size_t, int,
707 const struct sockaddr *, socklen_t);
708 static sendto_t real_sendto = NULL;
709 uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200710 int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200711
712 if (!real_sendto)
713 real_sendto = dlsym(RTLD_NEXT, "sendto");
714
715 if (dest_host == REMOTE_BSS_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200716 printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
717 dest_host, dest_port,
718 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200719 else if (dest_host == REMOTE_SGSN_ADDR)
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200720 printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
721 dest_host, dest_port,
722 len, osmo_hexdump(buf, len));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200723 else
724 return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
725
726 return len;
727}
728
729/* override */
730int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
731{
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200732 typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
733 static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200734 uint16_t bvci = msgb_bvci(msg);
735 uint16_t nsei = msgb_nsei(msg);
736
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200737 size_t len = msgb_length(msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200738
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200739 if (!real_gprs_ns_sendmsg)
740 real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
741
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200742 if (nsei == SGSN_NSEI)
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200743 printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, "
744 "msg length %d (%s)\n",
745 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200746 else
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200747 printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, "
748 "msg length %d (%s)\n",
749 bvci, len, __func__);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200750
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200751 return real_gprs_ns_sendmsg(nsi, msg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200752}
753
754static void dump_rate_ctr_group(FILE *stream, const char *prefix,
755 struct rate_ctr_group *ctrg)
756{
757 unsigned int i;
758
759 for (i = 0; i < ctrg->desc->num_ctr; i++) {
760 struct rate_ctr *ctr = &ctrg->ctr[i];
761 if (ctr->current && !strchr(ctrg->desc->ctr_desc[i].name, '.'))
762 fprintf(stream, " %s%s: %llu%s",
763 prefix, ctrg->desc->ctr_desc[i].description,
764 (long long)ctr->current,
765 "\n");
766 };
767}
768
769/* Signal handler for signals from NS layer */
770static int test_signal(unsigned int subsys, unsigned int signal,
771 void *handler_data, void *signal_data)
772{
773 struct ns_signal_data *nssd = signal_data;
774 int rc;
775
776 if (subsys != SS_L_NS)
777 return 0;
778
779 switch (signal) {
780 case S_NS_RESET:
781 printf("==> got signal NS_RESET, NS-VC 0x%04x/%s\n",
782 nssd->nsvc->nsvci,
783 gprs_ns_ll_str(nssd->nsvc));
784 break;
785
786 case S_NS_ALIVE_EXP:
787 printf("==> got signal NS_ALIVE_EXP, NS-VC 0x%04x/%s\n",
788 nssd->nsvc->nsvci,
789 gprs_ns_ll_str(nssd->nsvc));
790 break;
791
792 case S_NS_BLOCK:
793 printf("==> got signal NS_BLOCK, NS-VC 0x%04x/%s\n",
794 nssd->nsvc->nsvci,
795 gprs_ns_ll_str(nssd->nsvc));
796 break;
797
798 case S_NS_UNBLOCK:
799 printf("==> got signal NS_UNBLOCK, NS-VC 0x%04x/%s\n",
800 nssd->nsvc->nsvci,
801 gprs_ns_ll_str(nssd->nsvc));
802 break;
803
804 case S_NS_REPLACED:
805 printf("==> got signal NS_REPLACED: 0x%04x/%s",
806 nssd->nsvc->nsvci,
807 gprs_ns_ll_str(nssd->nsvc));
808 printf(" -> 0x%04x/%s\n",
809 nssd->old_nsvc->nsvci,
810 gprs_ns_ll_str(nssd->old_nsvc));
811 break;
812
813 default:
814 printf("==> got signal %d, NS-VC 0x%04x/%s\n", signal,
815 nssd->nsvc->nsvci,
816 gprs_ns_ll_str(nssd->nsvc));
817 break;
818 }
819 printf("\n");
820 rc = gbprox_signal(subsys, signal, handler_data, signal_data);
821 return rc;
822}
823
824static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len)
825{
826 struct msgb *msg;
827 int ret;
828 if (data_len > NS_ALLOC_SIZE - NS_ALLOC_HEADROOM) {
829 fprintf(stderr, "message too long: %d\n", data_len);
830 return -1;
831 }
832
833 msg = gprs_ns_msgb_alloc();
834 memmove(msg->data, data, data_len);
835 msg->l2h = msg->data;
836 msgb_put(msg, data_len);
837
838 printf("PROCESSING %s from 0x%08x:%d\n%s\n\n",
839 text, ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
840 osmo_hexdump(data, data_len));
841
842 ret = gprs_ns_rcvmsg(nsi, msg, peer, GPRS_NS_LL_UDP);
843
844 printf("result (%s) = %d\n\n", text, ret);
845
846 msgb_free(msg);
847
848 return ret;
849}
850
851static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
852{
853 struct gprs_nsvc *nsvc;
854
855 printf("Current NS-VCIs:\n");
856 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
857 struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200858 printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200859 nsvc->nsvci, nsvc->nsei,
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200860 ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
861 nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
862 nsvc->state & NSE_S_ALIVE ? "" : ", dead"
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200863 );
864 dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
865 }
866 printf("\n");
867}
868
869static void test_gbproxy()
870{
871 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
872 struct sockaddr_in bss_peer[4] = {{0},};
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200873 struct sockaddr_in sgsn_peer= {0};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200874
875 bssgp_nsi = nsi;
876 gbcfg.nsi = bssgp_nsi;
877 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
878
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +0200879 configure_sgsn_peer(&sgsn_peer);
880 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200881
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +0200882 printf("=== %s ===\n", __func__);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200883 printf("--- Initialise SGSN ---\n\n");
884
Jacob Erlbeck2e038f72014-07-07 10:46:00 +0200885 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200886 gprs_dump_nsi(nsi);
887
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200888 printf("--- Initialise BSS 1 ---\n\n");
889
890 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
891 setup_bssgp(nsi, &bss_peer[0], 0x1002);
892 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200893 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200894
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200895 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
896
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200897 printf("--- Initialise BSS 2 ---\n\n");
898
899 setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
900 setup_bssgp(nsi, &bss_peer[1], 0x2002);
901 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200902 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200903
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200904 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
905
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200906 printf("--- Move BSS 1 to new port ---\n\n");
907
908 setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
909 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200910 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200911
912 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
913
914 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
915 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200916 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200917
918 printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
919
920 setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000);
921 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200922 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200923
924 printf("--- Move BSS 2 to new port ---\n\n");
925
926 setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000);
927 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200928 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200929
930 printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
931
932 setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000);
933 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200934 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +0200935
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200936 printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
937
938 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
939 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200940 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200941
942 printf("--- Reset BSS 1 with a new BVCI ---\n\n");
943
944 setup_bssgp(nsi, &bss_peer[0], 0x1012);
945 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200946 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200947
948 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
949
950 printf("--- Reset BSS 1 with the old BVCI ---\n\n");
951
952 setup_bssgp(nsi, &bss_peer[0], 0x1002);
953 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200954 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200955
956 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
957
958 printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
959
960 setup_bssgp(nsi, &bss_peer[0], 0x1002);
961 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200962 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200963
964 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
965
966 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
967
968 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
969
970 printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
971
972 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
973
974 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
975
976 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
977
978 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
979
980 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
981
982 printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
983
984 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
985
986 printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
987
988 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
989
990 printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
991
992 setup_bssgp(nsi, &bss_peer[2], 0x1002);
993 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +0200994 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200995
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +0200996 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +0200997
Jacob Erlbeck2082afa2013-10-18 13:04:47 +0200998 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
999
1000 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1001
1002 send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
1003
1004 printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
1005
1006 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
1007
Jacob Erlbeckda890c72013-10-18 22:12:16 +02001008 printf("--- Send message from SGSN to BSS 1, BVCI 0x10ff (invalid) ---\n\n");
1009
1010 send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
1011
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001012 dump_global(stdout, 0);
Jacob Erlbeckda890c72013-10-18 22:12:16 +02001013
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001014 gbprox_reset(&gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001015 gprs_ns_destroy(nsi);
1016 nsi = NULL;
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001017}
1018
1019static void test_gbproxy_ident_changes()
1020{
1021 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1022 struct sockaddr_in bss_peer[1] = {{0},};
1023 struct sockaddr_in sgsn_peer= {0};
1024 uint16_t nsei[2] = {0x1000, 0x2000};
1025 uint16_t nsvci[2] = {0x1001, 0x2001};
1026 uint16_t bvci[4] = {0x1002, 0x2002, 0x3002, 0x4002};
1027
1028 bssgp_nsi = nsi;
1029 gbcfg.nsi = bssgp_nsi;
1030 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
1031
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001032 configure_sgsn_peer(&sgsn_peer);
1033 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001034
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001035 printf("=== %s ===\n", __func__);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001036 printf("--- Initialise SGSN ---\n\n");
1037
Jacob Erlbeck2e038f72014-07-07 10:46:00 +02001038 connect_sgsn(nsi, &sgsn_peer);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001039 gprs_dump_nsi(nsi);
1040
1041 printf("--- Initialise BSS 1 ---\n\n");
1042
1043 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[0]);
1044 gprs_dump_nsi(nsi);
1045
1046 printf("--- Setup BVCI 1 ---\n\n");
1047
1048 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1049 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001050 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001051
1052 printf("--- Setup BVCI 2 ---\n\n");
1053
1054 setup_bssgp(nsi, &bss_peer[0], bvci[1]);
1055 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001056 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001057
1058 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1059
1060 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1061 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1062
1063 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 ---\n\n");
1064
1065 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
1066 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
1067
1068 printf("--- Change NSEI ---\n\n");
1069
1070 setup_ns(nsi, &bss_peer[0], nsvci[0], nsei[1]);
1071 gprs_dump_nsi(nsi);
1072
1073 printf("--- Setup BVCI 1 ---\n\n");
1074
1075 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1076 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001077 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001078
1079 printf("--- Setup BVCI 3 ---\n\n");
1080
1081 setup_bssgp(nsi, &bss_peer[0], bvci[2]);
1082 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001083 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001084
1085 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1086
1087 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1088 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1089
1090 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1091 " (should fail) ---\n\n");
1092
1093 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001094 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001095 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001096 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001097
1098 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1099
1100 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1101 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1102
1103 printf("--- Change NSVCI ---\n\n");
1104
1105 setup_ns(nsi, &bss_peer[0], nsvci[1], nsei[1]);
1106 gprs_dump_nsi(nsi);
1107
1108 printf("--- Setup BVCI 1 ---\n\n");
1109
1110 setup_bssgp(nsi, &bss_peer[0], bvci[0]);
1111 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001112 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001113
1114 printf("--- Setup BVCI 4 ---\n\n");
1115
1116 setup_bssgp(nsi, &bss_peer[0], bvci[3]);
1117 send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001118 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001119
1120 printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
1121
1122 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[0], (uint8_t *)"", 0);
1123 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[0], (uint8_t *)"", 0);
1124
1125 printf("--- Send message from BSS 1 to SGSN and back, BVCI 2 "
1126 " (should fail) ---\n\n");
1127
1128 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001129 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001130 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001131 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001132
1133 printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
1134
1135 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[2], (uint8_t *)"", 0);
1136 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[2], (uint8_t *)"", 0);
1137
1138 printf("--- Send message from BSS 1 to SGSN and back, BVCI 4 ---\n\n");
1139
1140 send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0);
1141 send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
1142
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001143 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001144 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001145
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001146 gbprox_reset(&gbcfg);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02001147 gprs_ns_destroy(nsi);
1148 nsi = NULL;
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02001149}
1150
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001151static void test_gbproxy_ra_patching()
1152{
1153 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1154 struct sockaddr_in bss_peer[1] = {{0},};
1155 struct sockaddr_in sgsn_peer= {0};
1156 struct gprs_ra_id rai_bss =
1157 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1158 struct gprs_ra_id rai_sgsn =
1159 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
1160 struct gprs_ra_id rai_unknown =
1161 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001162 uint16_t cell_id = 0x7530;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001163 const char *err_msg = NULL;
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001164 const uint32_t ptmsi = 0xefe2b700;
1165 const uint32_t local_tlli = 0xefe2b700;
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001166 const uint32_t foreign_tlli = 0xbbc54679;
1167 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001168 struct gbproxy_tlli_info *tlli_info;
1169 struct gbproxy_peer *peer;
1170
1171 OSMO_ASSERT(local_tlli == gprs_tmsi2tlli(ptmsi, TLLI_LOCAL));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001172
1173 bssgp_nsi = nsi;
1174 gbcfg.nsi = bssgp_nsi;
1175 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
Jacob Erlbeck67a44452014-05-19 10:14:58 +02001176 gbcfg.core_mcc = 123;
1177 gbcfg.core_mnc = 456;
Jacob Erlbeck73685282014-05-23 20:48:07 +02001178 gbcfg.core_apn = talloc_zero_size(NULL, 100);
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +02001179 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001180 gbcfg.patch_ptmsi = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001181
Holger Hans Peter Freyther99a20d62014-07-07 14:19:10 +02001182 configure_sgsn_peer(&sgsn_peer);
1183 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001184
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001185 gbcfg.match_re = talloc_strdup(NULL, "^9898|^121314");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001186 if (gbproxy_set_patch_filter(&gbcfg, gbcfg.match_re, &err_msg) != 0) {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001187 fprintf(stderr, "Failed to compile RE '%s': %s\n",
1188 gbcfg.match_re, err_msg);
1189 exit(1);
1190 }
1191
1192
Jacob Erlbeckff0d65a2014-07-09 23:19:11 +02001193 printf("=== %s ===\n", __func__);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001194 printf("--- Initialise SGSN ---\n\n");
1195
1196 connect_sgsn(nsi, &sgsn_peer);
1197 gprs_dump_nsi(nsi);
1198
1199 printf("--- Initialise BSS 1 ---\n\n");
1200
1201 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1202 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1203 gprs_dump_nsi(nsi);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001204 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001205
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +02001206 peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001207 OSMO_ASSERT(peer != NULL);
1208
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001209 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1210
1211 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
1212 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
1213
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001214 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001215 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001216
1217 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1218
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001219 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1220 foreign_tlli, &rai_bss, cell_id,
1221 GPRS_SAPI_GMM, 0,
1222 dtap_attach_req, sizeof(dtap_attach_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001223
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001224 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1225 foreign_tlli, 0, NULL, 0,
1226 GPRS_SAPI_GMM, 0,
1227 dtap_identity_req, sizeof(dtap_identity_req));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001228
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001229 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1230 foreign_tlli, &rai_bss, cell_id,
1231 GPRS_SAPI_GMM, 3,
1232 dtap_identity_resp, sizeof(dtap_identity_resp));
Jacob Erlbeck690768a2014-08-06 15:16:45 +02001233
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001234 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1235 foreign_tlli, 1, imsi, sizeof(imsi),
1236 GPRS_SAPI_GMM, 1,
1237 dtap_attach_acc, sizeof(dtap_attach_acc));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001238
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001239 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001240 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001241 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1242 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1243 OSMO_ASSERT(!tlli_info->tlli.bss_validated);
1244 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1245 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1246 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1247 OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
1248 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001249
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001250 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1251 local_tlli, &rai_bss, cell_id,
1252 GPRS_SAPI_GMM, 4,
1253 dtap_attach_complete, sizeof(dtap_attach_complete));
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001254
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001255 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001256 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001257 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1258 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1259 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1260 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1261 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1262 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1263 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1264 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001265
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001266 /* Replace APN (1) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001267 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1268 local_tlli, &rai_bss, cell_id,
1269 GPRS_SAPI_GMM, 3,
1270 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001271
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001272 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001273 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001274 OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
1275 OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
1276 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1277 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1278 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
1279 OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
1280 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1281 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001282
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001283 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1284 local_tlli, 1, imsi, sizeof(imsi),
1285 GPRS_SAPI_GMM, 2,
1286 dtap_gmm_information, sizeof(dtap_gmm_information));
Jacob Erlbeck11669742014-06-06 18:47:36 +02001287
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001288 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001289 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001290 OSMO_ASSERT(tlli_info->tlli.assigned == 0);
1291 OSMO_ASSERT(tlli_info->tlli.current == local_tlli);
1292 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
1293 OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_tlli);
Jacob Erlbeck59748e62014-08-11 17:26:21 +02001294
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001295 /* Replace APN (2) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001296 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
1297 local_tlli, &rai_bss, cell_id,
1298 GPRS_SAPI_GMM, 3,
1299 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001300
Jacob Erlbeck73685282014-05-23 20:48:07 +02001301 gbcfg.core_apn[0] = 0;
1302 gbcfg.core_apn_size = 0;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001303
1304 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001305 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE 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 Erlbeck7b821d02014-08-08 08:37:37 +02001310 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001311
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001312 /* Detach */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001313 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1314 local_tlli, &rai_bss, cell_id,
1315 GPRS_SAPI_GMM, 6,
1316 dtap_detach_req, sizeof(dtap_detach_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001317
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001318 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1319 local_tlli, 1, imsi, sizeof(imsi),
1320 GPRS_SAPI_GMM, 5,
1321 dtap_detach_acc, sizeof(dtap_detach_acc));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001322
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001323 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001324
1325 printf("--- RA update ---\n\n");
1326
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001327 send_llc_ul_ui(nsi, "RA UPD REQ", &bss_peer[0], 0x1002,
1328 foreign_tlli, &rai_bss, 0x7080,
1329 GPRS_SAPI_GMM, 5,
1330 dtap_ra_upd_req, sizeof(dtap_ra_upd_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001331
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001332 send_llc_dl_ui(nsi, "RA UPD ACC", &sgsn_peer, 0x1002,
1333 foreign_tlli, 1, imsi, sizeof(imsi),
1334 GPRS_SAPI_GMM, 6,
1335 dtap_ra_upd_acc, sizeof(dtap_ra_upd_acc));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001336
1337 /* Remove APN */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001338 send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REMOVE APN)", &bss_peer[0], 0x1002,
1339 local_tlli, &rai_bss, cell_id,
1340 GPRS_SAPI_GMM, 3,
1341 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001342
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001343 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001344
Jacob Erlbeck3e23ddf2014-08-11 15:07:37 +02001345 /* Detach (power off -> no Detach Accept) */
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001346 send_llc_ul_ui(nsi, "DETACH REQ (PWR OFF)", &bss_peer[0], 0x1002,
1347 local_tlli, &rai_bss, cell_id,
1348 GPRS_SAPI_GMM, 6,
1349 dtap_detach_po_req, sizeof(dtap_detach_po_req));
Jacob Erlbeckaa3e3342014-06-27 11:55:04 +02001350
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001351 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001352 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001353
1354 printf("--- Bad cases ---\n\n");
1355
Jacob Erlbeck7c101d92014-06-06 18:49:23 +02001356 printf("TLLI is already detached, shouldn't patch\n");
Jacob Erlbeckc53f2a62014-08-15 14:56:28 +02001357 send_llc_ul_ui(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
1358 local_tlli, &rai_bss, cell_id,
1359 GPRS_SAPI_GMM, 3,
1360 dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
Jacob Erlbeckcf02eb12014-06-19 10:23:50 +02001361
Jacob Erlbeck006c0382014-05-27 13:49:04 +02001362 printf("Invalid RAI, shouldn't patch\n");
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001363 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
1364
Holger Hans Peter Freytherb9004592014-08-04 11:26:54 +02001365 dump_global(stdout, 0);
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001366 dump_peers(stdout, 0, 0, &gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001367
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02001368 gbprox_reset(&gbcfg);
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001369 gprs_ns_destroy(nsi);
1370 nsi = NULL;
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02001371}
1372
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001373static void test_gbproxy_ptmsi_patching()
1374{
1375 struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
1376 struct sockaddr_in bss_peer[1] = {{0},};
1377 struct sockaddr_in sgsn_peer= {0};
1378 struct gprs_ra_id rai_bss =
1379 {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
1380 struct gprs_ra_id rai_sgsn =
1381 {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
1382 struct gprs_ra_id rai_unknown =
1383 {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
1384 uint16_t cell_id = 0x1234;
1385
1386 const uint32_t sgsn_ptmsi = 0xefe2b700;
1387 const uint32_t local_sgsn_tlli = 0xefe2b700;
1388 const uint32_t random_sgsn_tlli = 0x7c69fb81;
1389
1390 const uint32_t bss_ptmsi = 0xc00f7304;
1391 const uint32_t local_bss_tlli = 0xc00f7304;
1392 const uint32_t foreign_bss_tlli = 0x8000dead;
1393
1394 const uint8_t imsi[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
1395 struct gbproxy_tlli_info *tlli_info;
1396 struct gbproxy_peer *peer;
1397 unsigned bss_nu = 0;
1398 unsigned sgsn_nu = 0;
1399
1400 OSMO_ASSERT(local_sgsn_tlli == gprs_tmsi2tlli(sgsn_ptmsi, TLLI_LOCAL));
1401
1402 bssgp_nsi = nsi;
1403 gbcfg.nsi = bssgp_nsi;
1404 gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
1405 gbcfg.core_mcc = 123;
1406 gbcfg.core_mnc = 456;
1407 gbcfg.core_apn = talloc_zero_size(NULL, 100);
1408 gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
1409 gbcfg.patch_ptmsi = 1;
1410 gbcfg.bss_ptmsi_state = 0;
1411 gbcfg.sgsn_tlli_state = 1;
1412
1413 configure_sgsn_peer(&sgsn_peer);
1414 configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
1415
1416 printf("=== %s ===\n", __func__);
1417 printf("--- Initialise SGSN ---\n\n");
1418
1419 connect_sgsn(nsi, &sgsn_peer);
1420
1421 printf("--- Initialise BSS 1 ---\n\n");
1422
1423 setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
1424 setup_bssgp(nsi, &bss_peer[0], 0x1002);
1425
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +02001426 peer = gbproxy_peer_by_nsei(&gbcfg, 0x1000);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001427 OSMO_ASSERT(peer != NULL);
1428
1429 send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
1430
1431 send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss);
1432 send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn);
1433
1434 gprs_dump_nsi(nsi);
1435 dump_global(stdout, 0);
1436 dump_peers(stdout, 0, 0, &gbcfg);
1437
1438 printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
1439
1440 send_llc_ul_ui(nsi, "ATTACH REQUEST", &bss_peer[0], 0x1002,
1441 foreign_bss_tlli, &rai_unknown, cell_id,
1442 GPRS_SAPI_GMM, bss_nu++,
1443 dtap_attach_req, sizeof(dtap_attach_req));
1444
1445 dump_peers(stdout, 0, 0, &gbcfg);
1446
1447 send_llc_dl_ui(nsi, "IDENT REQUEST", &sgsn_peer, 0x1002,
1448 random_sgsn_tlli, 0, NULL, 0,
1449 GPRS_SAPI_GMM, sgsn_nu++,
1450 dtap_identity_req, sizeof(dtap_identity_req));
1451
1452 dump_peers(stdout, 0, 0, &gbcfg);
1453
1454 send_llc_ul_ui(nsi, "IDENT RESPONSE", &bss_peer[0], 0x1002,
1455 foreign_bss_tlli, &rai_bss, cell_id,
1456 GPRS_SAPI_GMM, bss_nu++,
1457 dtap_identity_resp, sizeof(dtap_identity_resp));
1458
1459 dump_peers(stdout, 0, 0, &gbcfg);
1460
1461 send_llc_dl_ui(nsi, "ATTACH ACCEPT", &sgsn_peer, 0x1002,
1462 random_sgsn_tlli, 1, imsi, sizeof(imsi),
1463 GPRS_SAPI_GMM, sgsn_nu++,
1464 dtap_attach_acc, sizeof(dtap_attach_acc));
1465
1466 dump_peers(stdout, 0, 0, &gbcfg);
1467
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001468 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, random_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001469 OSMO_ASSERT(tlli_info);
1470 OSMO_ASSERT(tlli_info->tlli.assigned == local_bss_tlli);
1471 OSMO_ASSERT(tlli_info->tlli.current == foreign_bss_tlli);
1472 OSMO_ASSERT(!tlli_info->tlli.bss_validated);
1473 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1474 OSMO_ASSERT(tlli_info->tlli.ptmsi == bss_ptmsi);
1475 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_sgsn_tlli);
1476 OSMO_ASSERT(tlli_info->sgsn_tlli.current == random_sgsn_tlli);
1477 OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
1478 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
1479 OSMO_ASSERT(tlli_info->sgsn_tlli.ptmsi == sgsn_ptmsi);
1480
1481 send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
1482 local_bss_tlli, &rai_bss, cell_id,
1483 GPRS_SAPI_GMM, bss_nu++,
1484 dtap_attach_complete, sizeof(dtap_attach_complete));
1485
1486 dump_peers(stdout, 0, 0, &gbcfg);
1487
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001488 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001489 OSMO_ASSERT(tlli_info);
1490 OSMO_ASSERT(tlli_info->tlli.assigned == local_bss_tlli);
1491 OSMO_ASSERT(tlli_info->tlli.current == foreign_bss_tlli);
1492 OSMO_ASSERT(tlli_info->tlli.bss_validated);
1493 OSMO_ASSERT(!tlli_info->tlli.net_validated);
1494 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_sgsn_tlli);
1495 OSMO_ASSERT(tlli_info->sgsn_tlli.current == random_sgsn_tlli);
1496 OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
1497 OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
1498
1499 send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
1500 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1501 GPRS_SAPI_GMM, sgsn_nu++,
1502 dtap_gmm_information, sizeof(dtap_gmm_information));
1503
1504 dump_peers(stdout, 0, 0, &gbcfg);
1505
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001506 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, local_sgsn_tlli);
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02001507 OSMO_ASSERT(tlli_info);
1508 OSMO_ASSERT(tlli_info->tlli.current == local_bss_tlli);
1509 OSMO_ASSERT(tlli_info->tlli.assigned == 0);
1510 OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_sgsn_tlli);
1511 OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
1512
1513 /* Non-DTAP */
1514 send_bssgp_ul_unitdata(nsi, "XID (UL)", &bss_peer[0], 0x1002,
1515 local_bss_tlli, &rai_bss, cell_id,
1516 llc_u_xid_ul, sizeof(llc_u_xid_ul));
1517
1518 send_bssgp_dl_unitdata(nsi, "XID (DL)", &sgsn_peer, 0x1002,
1519 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1520 llc_u_xid_dl, sizeof(llc_u_xid_dl));
1521
1522 send_bssgp_ul_unitdata(nsi, "LL11 DNS QUERY (UL)", &bss_peer[0], 0x1002,
1523 local_bss_tlli, &rai_bss, cell_id,
1524 llc_ui_ll11_dns_query_ul,
1525 sizeof(llc_ui_ll11_dns_query_ul));
1526
1527 send_bssgp_dl_unitdata(nsi, "LL11 DNS RESP (DL)", &sgsn_peer, 0x1002,
1528 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1529 llc_ui_ll11_dns_resp_dl,
1530 sizeof(llc_ui_ll11_dns_resp_dl));
1531
1532 dump_peers(stdout, 0, 0, &gbcfg);
1533
1534 /* Detach */
1535 send_llc_ul_ui(nsi, "DETACH REQ", &bss_peer[0], 0x1002,
1536 local_bss_tlli, &rai_bss, cell_id,
1537 GPRS_SAPI_GMM, bss_nu++,
1538 dtap_detach_req, sizeof(dtap_detach_req));
1539
1540 dump_peers(stdout, 0, 0, &gbcfg);
1541
1542 send_llc_dl_ui(nsi, "DETACH ACC", &sgsn_peer, 0x1002,
1543 local_sgsn_tlli, 1, imsi, sizeof(imsi),
1544 GPRS_SAPI_GMM, sgsn_nu++,
1545 dtap_detach_acc, sizeof(dtap_detach_acc));
1546
1547 dump_peers(stdout, 0, 0, &gbcfg);
1548 dump_global(stdout, 0);
1549
1550 gbprox_reset(&gbcfg);
1551 gprs_ns_destroy(nsi);
1552 nsi = NULL;
1553}
1554
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001555/* TODO: Move tlv testing to libosmocore */
1556int v_fixed_shift(uint8_t **data, size_t *data_len, size_t len, uint8_t **value);
1557int tv_fixed_match(uint8_t **data, size_t *data_len, uint8_t tag, size_t len,
1558 uint8_t **value);
1559int tlv_match(uint8_t **data, size_t *data_len, uint8_t tag, uint8_t **value,
1560 size_t *value_len);
1561int lv_shift(uint8_t **data, size_t *data_len,
1562 uint8_t **value, size_t *value_len);
1563
1564static void check_tlv_match(uint8_t **data, size_t *data_len,
1565 uint8_t tag, size_t exp_len, const uint8_t *exp_val)
1566{
1567 uint8_t *value;
1568 size_t value_len;
1569 int rc;
1570
1571 rc = tlv_match(data, data_len, tag ^ 1, NULL, NULL);
1572 OSMO_ASSERT(rc == 0);
1573
1574 rc = tlv_match(data, data_len, tag, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001575 OSMO_ASSERT(rc == (int)value_len + 2);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001576 OSMO_ASSERT(value_len == exp_len);
1577 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1578}
1579
1580static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
1581 uint8_t tag, size_t len, const uint8_t *exp_val)
1582{
1583 uint8_t *value;
1584 int rc;
1585
1586 rc = tv_fixed_match(data, data_len, tag ^ 1, len, NULL);
1587 OSMO_ASSERT(rc == 0);
1588
1589 rc = tv_fixed_match(data, data_len, tag, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001590 OSMO_ASSERT(rc == (int)len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001591 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1592}
1593
1594static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
1595 size_t len, const uint8_t *exp_val)
1596{
1597 uint8_t *value;
1598 int rc;
1599
1600 rc = v_fixed_shift(data, data_len, len, &value);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001601 OSMO_ASSERT(rc == (int)len);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001602 OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
1603}
1604
1605static void check_lv_shift(uint8_t **data, size_t *data_len,
1606 size_t exp_len, const uint8_t *exp_val)
1607{
1608 uint8_t *value;
1609 size_t value_len;
1610 int rc;
1611
1612 rc = lv_shift(data, data_len, &value, &value_len);
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001613 OSMO_ASSERT(rc == (int)value_len + 1);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001614 OSMO_ASSERT(value_len == exp_len);
1615 OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
1616}
1617
1618static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
1619 const uint8_t *test_data)
1620{
1621 uint8_t buf[300] = {0};
1622
1623 uint8_t *unchanged_ptr = buf - 1;
1624 size_t unchanged_len = 0xdead;
1625 size_t tmp_data_len = data_len;
1626 uint8_t *value = unchanged_ptr;
1627 size_t value_len = unchanged_len;
1628 uint8_t *data = buf;
1629
1630 OSMO_ASSERT(data_len <= sizeof(buf));
1631
1632 tlv_put(data, tag, len, test_data);
1633 if (data_len < len + 2) {
1634 OSMO_ASSERT(-1 == tlv_match(&data, &tmp_data_len,
1635 tag, &value, &value_len));
1636 OSMO_ASSERT(tmp_data_len == 0);
1637 OSMO_ASSERT(data == buf + data_len);
1638 OSMO_ASSERT(value == unchanged_ptr);
1639 OSMO_ASSERT(value_len == unchanged_len);
1640 } else {
1641 OSMO_ASSERT(0 <= tlv_match(&data, &tmp_data_len,
1642 tag, &value, &value_len));
1643 OSMO_ASSERT(value != unchanged_ptr);
1644 OSMO_ASSERT(value_len != unchanged_len);
1645 }
1646}
1647
1648static void check_tv_fixed_match_data_len(size_t data_len,
1649 uint8_t tag, size_t len,
1650 const uint8_t *test_data)
1651{
1652 uint8_t buf[300] = {0};
1653
1654 uint8_t *unchanged_ptr = buf - 1;
1655 size_t tmp_data_len = data_len;
1656 uint8_t *value = unchanged_ptr;
1657 uint8_t *data = buf;
1658
1659 OSMO_ASSERT(data_len <= sizeof(buf));
1660
1661 tv_fixed_put(data, tag, len, test_data);
1662
1663 if (data_len < len + 1) {
1664 OSMO_ASSERT(-1 == tv_fixed_match(&data, &tmp_data_len,
1665 tag, len, &value));
1666 OSMO_ASSERT(tmp_data_len == 0);
1667 OSMO_ASSERT(data == buf + data_len);
1668 OSMO_ASSERT(value == unchanged_ptr);
1669 } else {
1670 OSMO_ASSERT(0 <= tv_fixed_match(&data, &tmp_data_len,
1671 tag, len, &value));
1672 OSMO_ASSERT(value != unchanged_ptr);
1673 }
1674}
1675
1676static void check_v_fixed_shift_data_len(size_t data_len,
1677 size_t len, const uint8_t *test_data)
1678{
1679 uint8_t buf[300] = {0};
1680
1681 uint8_t *unchanged_ptr = buf - 1;
1682 size_t tmp_data_len = data_len;
1683 uint8_t *value = unchanged_ptr;
1684 uint8_t *data = buf;
1685
1686 OSMO_ASSERT(data_len <= sizeof(buf));
1687
1688 memcpy(data, test_data, len);
1689
1690 if (data_len < len) {
1691 OSMO_ASSERT(-1 == v_fixed_shift(&data, &tmp_data_len,
1692 len, &value));
1693 OSMO_ASSERT(tmp_data_len == 0);
1694 OSMO_ASSERT(data == buf + data_len);
1695 OSMO_ASSERT(value == unchanged_ptr);
1696 } else {
1697 OSMO_ASSERT(0 <= v_fixed_shift(&data, &tmp_data_len,
1698 len, &value));
1699 OSMO_ASSERT(value != unchanged_ptr);
1700 }
1701}
1702
1703static void check_lv_shift_data_len(size_t data_len,
1704 size_t len, const uint8_t *test_data)
1705{
1706 uint8_t buf[300] = {0};
1707
1708 uint8_t *unchanged_ptr = buf - 1;
1709 size_t unchanged_len = 0xdead;
1710 size_t tmp_data_len = data_len;
1711 uint8_t *value = unchanged_ptr;
1712 size_t value_len = unchanged_len;
1713 uint8_t *data = buf;
1714
1715 lv_put(data, len, test_data);
1716 if (data_len < len + 1) {
1717 OSMO_ASSERT(-1 == lv_shift(&data, &tmp_data_len,
1718 &value, &value_len));
1719 OSMO_ASSERT(tmp_data_len == 0);
1720 OSMO_ASSERT(data == buf + data_len);
1721 OSMO_ASSERT(value == unchanged_ptr);
1722 OSMO_ASSERT(value_len == unchanged_len);
1723 } else {
1724 OSMO_ASSERT(0 <= lv_shift(&data, &tmp_data_len,
1725 &value, &value_len));
1726 OSMO_ASSERT(value != unchanged_ptr);
1727 OSMO_ASSERT(value_len != unchanged_len);
1728 }
1729}
1730
1731static void test_tlv_shift_functions()
1732{
1733 uint8_t test_data[1024];
1734 uint8_t buf[1024];
1735 uint8_t *data_end;
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001736 unsigned i, len;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001737 uint8_t *data;
1738 size_t data_len;
1739 const uint8_t tag = 0x1a;
1740
1741 printf("Test shift functions\n");
1742
1743 for (i = 0; i < ARRAY_SIZE(test_data); i++)
1744 test_data[i] = (uint8_t)i;
1745
1746 for (len = 0; len < 256; len++) {
Jacob Erlbeck948b7302014-08-11 10:37:35 +02001747 const unsigned iterations = sizeof(buf) / (len + 2) / 4;
Jacob Erlbeckb1381062014-07-01 12:41:13 +02001748
1749 memset(buf, 0xee, sizeof(buf));
1750 data_end = data = buf;
1751
1752 for (i = 0; i < iterations; i++) {
1753 data_end = tlv_put(data_end, tag, len, test_data);
1754 data_end = tv_fixed_put(data_end, tag, len, test_data);
1755 /* v_fixed_put */
1756 memcpy(data_end, test_data, len);
1757 data_end += len;
1758 data_end = lv_put(data_end, len, test_data);
1759 }
1760
1761 data_len = data_end - data;
1762 OSMO_ASSERT(data_len <= sizeof(buf));
1763
1764 for (i = 0; i < iterations; i++) {
1765 check_tlv_match(&data, &data_len, tag, len, test_data);
1766 check_tv_fixed_match(&data, &data_len, tag, len, test_data);
1767 check_v_fixed_shift(&data, &data_len, len, test_data);
1768 check_lv_shift(&data, &data_len, len, test_data);
1769 }
1770
1771 OSMO_ASSERT(data == data_end);
1772
1773 /* Test at end of data */
1774
1775 OSMO_ASSERT(-1 == tlv_match(&data, &data_len, tag, NULL, NULL));
1776 OSMO_ASSERT(-1 == tv_fixed_match(&data, &data_len, tag, len, NULL));
1777 OSMO_ASSERT((len ? -1 : 0) == v_fixed_shift(&data, &data_len, len, NULL));
1778 OSMO_ASSERT(-1 == lv_shift(&data, &data_len, NULL, NULL));
1779
1780 /* Test invalid data_len */
1781 for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
1782 check_tlv_match_data_len(data_len, tag, len, test_data);
1783 check_tv_fixed_match_data_len(data_len, tag, len, test_data);
1784 check_v_fixed_shift_data_len(data_len, len, test_data);
1785 check_lv_shift_data_len(data_len, len, test_data);
1786 }
1787 }
1788}
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001789
1790static void test_gbproxy_tlli_expire(void)
1791{
1792 struct gbproxy_config cfg = {0};
1793 struct gbproxy_peer *peer;
1794 const char *err_msg = NULL;
1795 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0x26 };
1796 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI, 0x26, 0x27, 0x28, 0x29 };
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001797 const uint8_t imsi3[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0x76, 0xf8 };
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001798 const uint32_t tlli1 = 1234 | 0xc0000000;
1799 const uint32_t tlli2 = 5678 | 0xc0000000;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001800 const uint32_t tlli3 = 3456 | 0xc0000000;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001801 const char *filter_re = ".*";
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001802 time_t now = 1407479214;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001803
1804 printf("Test TLLI info expiry\n\n");
1805
1806 gbproxy_init_config(&cfg);
1807
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001808 if (gbproxy_set_patch_filter(&cfg, filter_re, &err_msg) != 0) {
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001809 fprintf(stderr, "gbprox_set_patch_filter: got error: %s\n",
1810 err_msg);
1811 OSMO_ASSERT(err_msg == NULL);
1812 }
1813
1814 {
1815 struct gbproxy_tlli_info *tlli_info;
1816
1817 printf("Test TLLI replacement:\n");
1818
1819 cfg.tlli_max_len = 0;
1820 cfg.tlli_max_age = 0;
1821 peer = gbproxy_peer_alloc(&cfg, 20);
1822 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1823
1824 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001825 tlli_info = gbproxy_register_tlli(peer, tlli1,
1826 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001827 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001828 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001829 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1830
1831 /* replace the old entry */
1832 printf(" Add TLLI 2, IMSI 1 (should replace TLLI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001833 tlli_info = gbproxy_register_tlli(peer, tlli2,
1834 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001835 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001836 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001837 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1838
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001839 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001840
1841 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001842 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001843 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001844 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001845 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001846 OSMO_ASSERT(!tlli_info);
1847
1848 printf("\n");
1849
1850 gbproxy_peer_free(peer);
1851 }
1852
1853 {
1854 struct gbproxy_tlli_info *tlli_info;
1855
1856 printf("Test IMSI replacement:\n");
1857
1858 cfg.tlli_max_len = 0;
1859 cfg.tlli_max_age = 0;
1860 peer = gbproxy_peer_alloc(&cfg, 20);
1861 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1862
1863 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001864 tlli_info = gbproxy_register_tlli(peer, tlli1,
1865 imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001866 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001867 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001868 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1869
1870 /* try to replace the old entry */
1871 printf(" Add TLLI 1, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001872 tlli_info = gbproxy_register_tlli(peer, tlli1,
1873 imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeck5e68ecf2014-08-07 20:18:47 +02001874 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001875 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001876 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1877
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001878 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001879
1880 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001881 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001882 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001883 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001884 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001885 OSMO_ASSERT(tlli_info->tlli.current == tlli1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001886
1887 printf("\n");
1888
1889 gbproxy_peer_free(peer);
1890 }
1891
1892 {
1893 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001894 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001895
1896 printf("Test TLLI expiry, max_len == 1:\n");
1897
1898 cfg.tlli_max_len = 1;
1899 cfg.tlli_max_age = 0;
1900 peer = gbproxy_peer_alloc(&cfg, 20);
1901 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1902
1903 printf(" Add TLLI 1, IMSI 1\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001904 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001905 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1906
1907 /* replace the old entry */
1908 printf(" Add TLLI 2, IMSI 2 (should replace IMSI 1)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001909 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2), now);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001910 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1911
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001912 num_removed = gbproxy_remove_stale_tllis(peer, time(NULL) + 2);
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001913 OSMO_ASSERT(num_removed == 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001914 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1915
Jacob Erlbeck7b821d02014-08-08 08:37:37 +02001916 dump_peers(stdout, 2, now, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001917
1918 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001919 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001920 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001921 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001922 OSMO_ASSERT(tlli_info);
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001923 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001924
1925 printf("\n");
1926
1927 gbproxy_peer_free(peer);
1928 }
1929
1930 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001931 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckaad32bc2014-08-07 17:23:00 +02001932 int num_removed;
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001933
1934 printf("Test TLLI expiry, max_age == 1:\n");
1935
1936 cfg.tlli_max_len = 0;
1937 cfg.tlli_max_age = 1;
1938 peer = gbproxy_peer_alloc(&cfg, 20);
1939 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1940
1941 printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001942 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001943 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1944
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001945 printf(" Add TLLI 2, IMSI 2 (should not expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001946 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001947 now + 1);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001948 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1949
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001950 num_removed = gbproxy_remove_stale_tllis(peer, now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001951 OSMO_ASSERT(num_removed == 1);
1952 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1953
1954 dump_peers(stdout, 2, now + 2, &cfg);
1955
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001956 /* verify that 5678 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001957 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001958 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001959 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001960 OSMO_ASSERT(tlli_info);
1961 OSMO_ASSERT(tlli_info->tlli.current == tlli2);
1962
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001963 printf("\n");
1964
1965 gbproxy_peer_free(peer);
1966 }
1967
1968 {
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02001969 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001970 int num_removed;
1971
1972 printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
1973
1974 cfg.tlli_max_len = 0;
1975 cfg.tlli_max_age = 1;
1976 peer = gbproxy_peer_alloc(&cfg, 20);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02001977 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 0);
1978
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001979 printf(" Add TLLI 1, IMSI 1 (should expire)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001980 gbproxy_register_tlli(peer, tlli1, imsi1, ARRAY_SIZE(imsi1), now);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001981 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1982
1983 printf(" Add TLLI 2, IMSI 2 (should expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001984 gbproxy_register_tlli(peer, tlli2, imsi2, ARRAY_SIZE(imsi2),
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001985 now + 1);
1986 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 2);
1987
1988 printf(" Add TLLI 3, IMSI 3 (should not expire after timeout)\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001989 gbproxy_register_tlli(peer, tlli3, imsi3, ARRAY_SIZE(imsi3),
1990 now + 2);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001991 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 3);
1992
1993 dump_peers(stdout, 2, now + 2, &cfg);
1994
1995 printf(" Remove stale TLLIs\n");
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001996 num_removed = gbproxy_remove_stale_tllis(peer, now + 3);
Jacob Erlbeckf4946202014-08-08 09:33:06 +02001997 OSMO_ASSERT(num_removed == 2);
1998 OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
1999
2000 dump_peers(stdout, 2, now + 2, &cfg);
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002001
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002002 /* verify that tlli3 has survived */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002003 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002004 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002005 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002006 OSMO_ASSERT(!tlli_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002007 tlli_info = gbproxy_find_tlli_by_mi(peer, imsi3, ARRAY_SIZE(imsi3));
Jacob Erlbeck9057bc32014-08-12 16:30:30 +02002008 OSMO_ASSERT(tlli_info);
2009 OSMO_ASSERT(tlli_info->tlli.current == tlli3);
2010
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002011 printf("\n");
2012
2013 gbproxy_peer_free(peer);
2014 }
2015}
2016
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002017static void test_gbproxy_imsi_matching(void)
2018{
2019 struct gbproxy_config cfg = {0};
2020 struct gbproxy_peer *peer;
2021 const char *err_msg = NULL;
2022 const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI | 0x10, 0x32, 0x54, 0xf6 };
2023 const uint8_t imsi2[] = { GSM_MI_TYPE_IMSI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
2024 const uint8_t imsi3_bad[] = { GSM_MI_TYPE_IMSI | 0x10, 0xee, 0x54, 0xff };
2025 const uint8_t tmsi1[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22, 0x33, 0x44 };
2026 const uint8_t tmsi2_bad[] = { GSM_MI_TYPE_TMSI | 0xf0, 0x11, 0x22 };
2027 const uint8_t imei1[] = { GSM_MI_TYPE_IMEI | 0x10, 0x32, 0x54, 0xf6 };
2028 const uint8_t imei2[] = { GSM_MI_TYPE_IMEI | GSM_MI_ODD | 0x10, 0x32, 0x54, 0x76 };
2029 const char *filter_re1 = ".*";
2030 const char *filter_re2 = "^1234";
2031 const char *filter_re3 = "^4321";
2032 const char *filter_re4_bad = "^12[";
2033
2034 printf("=== Test IMSI/TMSI matching ===\n\n");
2035
2036 gbproxy_init_config(&cfg);
2037 OSMO_ASSERT(cfg.check_imsi == 0);
2038
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002039 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re1, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002040 OSMO_ASSERT(cfg.check_imsi == 1);
2041
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002042 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002043 OSMO_ASSERT(cfg.check_imsi == 1);
2044
2045 err_msg = NULL;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002046 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re4_bad, &err_msg) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002047 OSMO_ASSERT(err_msg != NULL);
2048 OSMO_ASSERT(cfg.check_imsi == 0);
2049
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002050 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002051 OSMO_ASSERT(cfg.check_imsi == 1);
2052
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002053 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, NULL, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002054 OSMO_ASSERT(cfg.check_imsi == 0);
2055
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002056 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck29805da2014-08-14 08:57:04 +02002057 OSMO_ASSERT(cfg.check_imsi == 1);
2058
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002059 gbproxy_clear_patch_filter(&cfg);
Jacob Erlbeck29805da2014-08-14 08:57:04 +02002060 OSMO_ASSERT(cfg.check_imsi == 0);
2061
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002062 peer = gbproxy_peer_alloc(&cfg, 20);
2063
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002064 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re2, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002065 OSMO_ASSERT(cfg.check_imsi == 1);
2066
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002067 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 1);
2068 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002069 /* imsi3_bad contains 0xE and 0xF digits, but the conversion function
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002070 * doesn't complain, so gbproxy_check_imsi() doesn't return -1 in this
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002071 * case. */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002072 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
2073 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
2074 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
2075 OSMO_ASSERT(gbproxy_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
2076 OSMO_ASSERT(gbproxy_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002077
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002078 OSMO_ASSERT(gbproxy_set_patch_filter(&cfg, filter_re3, &err_msg) == 0);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002079 OSMO_ASSERT(cfg.check_imsi == 1);
2080
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02002081 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi1, ARRAY_SIZE(imsi1)) == 0);
2082 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi2, ARRAY_SIZE(imsi2)) == 0);
2083 OSMO_ASSERT(gbproxy_check_imsi(peer, imsi3_bad, ARRAY_SIZE(imsi3_bad)) == 0);
2084 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi1, ARRAY_SIZE(tmsi1)) == -1);
2085 OSMO_ASSERT(gbproxy_check_imsi(peer, tmsi2_bad, ARRAY_SIZE(tmsi2_bad)) == -1);
2086 OSMO_ASSERT(gbproxy_check_imsi(peer, imei1, ARRAY_SIZE(imei1)) == -1);
2087 OSMO_ASSERT(gbproxy_check_imsi(peer, imei2, ARRAY_SIZE(imei2)) == -1);
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002088
2089 /* TODO: Check correct length but wrong type with is_mi_tmsi */
2090
2091 gbproxy_peer_free(peer);
2092}
2093
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002094static struct log_info_cat gprs_categories[] = {
2095 [DGPRS] = {
2096 .name = "DGPRS",
2097 .description = "GPRS Packet Service",
2098 .enabled = 1, .loglevel = LOGL_DEBUG,
2099 },
2100 [DNS] = {
2101 .name = "DNS",
2102 .description = "GPRS Network Service (NS)",
2103 .enabled = 1, .loglevel = LOGL_INFO,
2104 },
2105 [DBSSGP] = {
2106 .name = "DBSSGP",
2107 .description = "GPRS BSS Gateway Protocol (BSSGP)",
2108 .enabled = 1, .loglevel = LOGL_DEBUG,
2109 },
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002110};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002111
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002112static struct log_info info = {
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002113 .cat = gprs_categories,
2114 .num_cat = ARRAY_SIZE(gprs_categories),
Holger Hans Peter Freyther2840b3f2014-07-07 19:48:14 +02002115};
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002116
2117int main(int argc, char **argv)
2118{
2119 osmo_init_logging(&info);
2120 log_set_use_color(osmo_stderr_target, 0);
2121 log_set_print_filename(osmo_stderr_target, 0);
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +02002122 osmo_signal_register_handler(SS_L_NS, &test_signal, &gbcfg);
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002123
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002124 log_set_print_filename(osmo_stderr_target, 0);
Jacob Erlbeck627e7d92014-07-03 13:28:13 +02002125 log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
2126 log_set_all_filter(osmo_stderr_target, 1);
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002127
2128 rate_ctr_init(NULL);
2129
2130 setlinebuf(stdout);
2131
2132 printf("===== GbProxy test START\n");
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +02002133 gbproxy_init_config(&gbcfg);
Jacob Erlbeckb1381062014-07-01 12:41:13 +02002134 test_tlv_shift_functions();
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002135 test_gbproxy();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002136 test_gbproxy_ident_changes();
Jacob Erlbeck291f0502014-08-07 10:46:29 +02002137 test_gbproxy_imsi_matching();
Jacob Erlbeck7fb42db2014-07-07 10:46:01 +02002138 test_gbproxy_ra_patching();
Jacob Erlbeck6bd7ded2014-08-15 17:20:06 +02002139 test_gbproxy_ptmsi_patching();
Holger Hans Peter Freyther0196c992014-08-04 17:10:08 +02002140 test_gbproxy_tlli_expire();
Jacob Erlbeck72b401f2013-10-24 12:48:55 +02002141 printf("===== GbProxy test END\n\n");
Jacob Erlbeck51a869c2013-10-15 12:00:26 +02002142
2143 exit(EXIT_SUCCESS);
2144}