blob: 70e98d721209ce1ef3fa8460f1e11dd878985fe5 [file] [log] [blame]
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +08001/*
2 * BSC NAT Message filtering
3 *
4 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freytherdf6143a2010-06-15 18:46:56 +08005 * (C) 2010 by On-Waves
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +08006 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25
26#include <openbsc/debug.h>
27#include <openbsc/gsm_data.h>
28#include <openbsc/bsc_nat.h>
29
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +080030#include <osmocore/talloc.h>
31
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080032#include <stdio.h>
33
34/* test messages for ipa */
35static u_int8_t ipa_id[] = {
36 0x00, 0x01, 0xfe, 0x06,
37};
38
39/* SCCP messages are below */
40static u_int8_t gsm_reset[] = {
41 0x00, 0x12, 0xfd,
42 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
43 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
44 0x01, 0x20,
45};
46
47static const u_int8_t gsm_reset_ack[] = {
48 0x00, 0x13, 0xfd,
49 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
50 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
51 0x00, 0x01, 0x31,
52};
53
54static const u_int8_t gsm_paging[] = {
55 0x00, 0x20, 0xfd,
56 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
57 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x10,
58 0x00, 0x0e, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10,
59 0x02, 0x01, 0x31, 0x97, 0x61, 0x1a, 0x01, 0x06,
60};
61
62/* BSC -> MSC connection open */
63static const u_int8_t bssmap_cr[] = {
64 0x00, 0x2c, 0xfd,
65 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x04, 0x02,
66 0x42, 0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05,
67 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x12, 0xc3,
68 0x50, 0x17, 0x10, 0x05, 0x24, 0x11, 0x03, 0x33,
69 0x19, 0xa2, 0x08, 0x29, 0x47, 0x10, 0x02, 0x01,
70 0x31, 0x97, 0x61, 0x00
71};
72
73/* MSC -> BSC connection confirm */
74static const u_int8_t bssmap_cc[] = {
75 0x00, 0x0a, 0xfd,
76 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
77};
78
79/* MSC -> BSC released */
80static const u_int8_t bssmap_released[] = {
81 0x00, 0x0e, 0xfd,
82 0x04, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x01, 0x0f,
83 0x02, 0x23, 0x42, 0x00,
84};
85
86/* BSC -> MSC released */
87static const u_int8_t bssmap_release_complete[] = {
88 0x00, 0x07, 0xfd,
89 0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
90};
91
92struct filter_result {
93 const u_int8_t *data;
94 const u_int16_t length;
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +010095 const int dir;
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +080096 const int result;
97};
98
99static const struct filter_result results[] = {
100 {
101 .data = ipa_id,
102 .length = ARRAY_SIZE(ipa_id),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100103 .dir = DIR_MSC,
104 .result = 1,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800105 },
106 {
107 .data = gsm_reset,
108 .length = ARRAY_SIZE(gsm_reset),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100109 .dir = DIR_MSC,
110 .result = 1,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800111 },
112 {
113 .data = gsm_reset_ack,
114 .length = ARRAY_SIZE(gsm_reset_ack),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100115 .dir = DIR_BSC,
116 .result = 1,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800117 },
118 {
119 .data = gsm_paging,
120 .length = ARRAY_SIZE(gsm_paging),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100121 .dir = DIR_BSC,
122 .result = 0,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800123 },
124 {
125 .data = bssmap_cr,
126 .length = ARRAY_SIZE(bssmap_cr),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100127 .dir = DIR_MSC,
128 .result = 0,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800129 },
130 {
131 .data = bssmap_cc,
132 .length = ARRAY_SIZE(bssmap_cc),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100133 .dir = DIR_BSC,
134 .result = 0,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800135 },
136 {
137 .data = bssmap_released,
138 .length = ARRAY_SIZE(bssmap_released),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100139 .dir = DIR_MSC,
140 .result = 0,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800141 },
142 {
143 .data = bssmap_release_complete,
144 .length = ARRAY_SIZE(bssmap_release_complete),
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100145 .dir = DIR_BSC,
146 .result = 0,
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800147 },
148};
149
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800150static void test_filter(void)
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800151{
152 int i;
153
154
155 /* start testinh with proper messages */
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800156 fprintf(stderr, "Testing BSS Filtering.\n");
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800157 for (i = 0; i < ARRAY_SIZE(results); ++i) {
158 int result;
159 struct bsc_nat_parsed *parsed;
160 struct msgb *msg = msgb_alloc(4096, "test-message");
161
162 fprintf(stderr, "Going to test item: %d\n", i);
163 memcpy(msg->data, results[i].data, results[i].length);
164 msg->l2h = msgb_put(msg, results[i].length);
165
166 parsed = bsc_nat_parse(msg);
167 if (!parsed) {
168 fprintf(stderr, "FAIL: Failed to parse the message\n");
169 continue;
170 }
171
Holger Hans Peter Freyther1d6fb182010-01-30 11:53:30 +0100172 result = bsc_nat_filter_ipa(results[i].dir, msg, parsed);
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800173 if (result != results[i].result) {
174 fprintf(stderr, "FAIL: Not the expected result got: %d wanted: %d\n",
175 result, results[i].result);
176 }
177
178 msgb_free(msg);
179 }
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800180}
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800181
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800182#include "bsc_data.c"
183
184static void copy_to_msg(struct msgb *msg, const u_int8_t *data, unsigned int length)
185{
186 msgb_reset(msg);
187 msg->l2h = msgb_put(msg, length);
188 memcpy(msg->l2h, data, msgb_l2len(msg));
189}
190
191#define VERIFY(con_found, con, msg, ver, str) \
Holger Hans Peter Freyther49c7fb52010-06-15 18:48:55 +0800192 if (!con_found || con_found->bsc != con) { \
Holger Hans Peter Freyther72ba1622010-06-15 18:48:44 +0800193 fprintf(stderr, "Failed to find the con: %p\n", con_found); \
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800194 abort(); \
195 } \
196 if (memcmp(msg->data, ver, sizeof(ver)) != 0) { \
197 fprintf(stderr, "Failed to patch the %s msg.\n", str); \
198 abort(); \
199 }
200
201/* test conn tracking once */
202static void test_contrack()
203{
204 int rc;
205 struct bsc_nat *nat;
Holger Hans Peter Freyther49c7fb52010-06-15 18:48:55 +0800206 struct bsc_connection *con;
207 struct sccp_connections *con_found;
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800208 struct bsc_nat_parsed *parsed;
209 struct msgb *msg;
210
211 fprintf(stderr, "Testing connection tracking.\n");
212 nat = bsc_nat_alloc();
213 con = bsc_connection_alloc(nat);
214 msg = msgb_alloc(4096, "test");
215
216 /* 1.) create a connection */
217 copy_to_msg(msg, bsc_cr, sizeof(bsc_cr));
218 parsed = bsc_nat_parse(msg);
219 con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
220 if (con_found != NULL) {
Holger Hans Peter Freyther72ba1622010-06-15 18:48:44 +0800221 fprintf(stderr, "Con should not exist %p\n", con_found);
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800222 abort();
223 }
224 rc = create_sccp_src_ref(con, msg, parsed);
225 if (rc != 0) {
226 fprintf(stderr, "Failed to create a ref\n");
227 abort();
228 }
229 con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
Holger Hans Peter Freyther49c7fb52010-06-15 18:48:55 +0800230 if (!con_found || con_found->bsc != con) {
Holger Hans Peter Freyther72ba1622010-06-15 18:48:44 +0800231 fprintf(stderr, "Failed to find the con: %p\n", con_found);
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800232 abort();
233 }
234 if (memcmp(msg->data, bsc_cr_patched, sizeof(bsc_cr_patched)) != 0) {
235 fprintf(stderr, "Failed to patch the BSC CR msg.\n");
236 abort();
237 }
238 talloc_free(parsed);
239
240 /* 2.) get the cc */
241 copy_to_msg(msg, msc_cc, sizeof(msc_cc));
242 parsed = bsc_nat_parse(msg);
Holger Hans Peter Freyther49c7fb52010-06-15 18:48:55 +0800243 con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
244 VERIFY(con_found, con, msg, msc_cc_patched, "MSC CC");
245 if (update_sccp_src_ref(con_found, parsed) != 0) {
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800246 fprintf(stderr, "Failed to update the SCCP con.\n");
247 abort();
248 }
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800249
250 /* 3.) send some data */
251 copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
252 parsed = bsc_nat_parse(msg);
253 con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
254 VERIFY(con_found, con, msg, bsc_dtap_patched, "BSC DTAP");
255
256 /* 4.) receive some data */
257 copy_to_msg(msg, msc_dtap, sizeof(msc_dtap));
258 parsed = bsc_nat_parse(msg);
259 con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
260 VERIFY(con_found, con, msg, msc_dtap_patched, "MSC DTAP");
261
262 /* 5.) close the connection */
263 copy_to_msg(msg, msc_rlsd, sizeof(msc_rlsd));
264 parsed = bsc_nat_parse(msg);
265 con_found = patch_sccp_src_ref_to_bsc(msg, parsed, nat);
266 VERIFY(con_found, con, msg, msc_rlsd_patched, "MSC RLSD");
267
268 /* 6.) confirm the connection close */
269 copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
270 parsed = bsc_nat_parse(msg);
271 con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
Holger Hans Peter Freyther49c7fb52010-06-15 18:48:55 +0800272 if (!con_found || con_found->bsc != con) {
Holger Hans Peter Freyther72ba1622010-06-15 18:48:44 +0800273 fprintf(stderr, "Failed to find the con: %p\n", con_found);
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800274 abort();
275 }
276 if (memcmp(msg->data, bsc_rlc_patched, sizeof(bsc_rlc_patched)) != 0) {
277 fprintf(stderr, "Failed to patch the BSC CR msg.\n");
278 abort();
279 }
280 remove_sccp_src_ref(con, msg, parsed);
281 con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
282
283 /* verify that it is gone */
284 if (con_found != NULL) {
Holger Hans Peter Freyther72ba1622010-06-15 18:48:44 +0800285 fprintf(stderr, "Con should be gone. %p\n", con_found);
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800286 abort();
287 }
288 talloc_free(parsed);
289
290
291 talloc_free(nat);
292 msgb_free(msg);
293}
294
Holger Hans Peter Freyther04fd9922010-03-30 06:51:53 +0200295static void test_paging(void)
296{
297 struct bsc_nat *nat;
298 struct bsc_connection *con;
299 struct bsc_nat_parsed *parsed;
300 struct msgb *msg;
301
302 fprintf(stderr, "Testing paging by lac.\n");
303
304 nat = bsc_nat_alloc();
305 con = bsc_connection_alloc(nat);
306 con->lac = 23;
307 con->authenticated = 1;
308 llist_add(&con->list_entry, &nat->bsc_connections);
309 msg = msgb_alloc(4096, "test");
310
311 /* Test completely bad input */
312 copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
313 if (bsc_nat_find_bsc(nat, msg) != 0) {
314 fprintf(stderr, "Should have not found anything.\n");
315 abort();
316 }
317
318 /* Test it by not finding it */
319 copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
320 parsed = bsc_nat_parse(msg);
321 if (bsc_nat_find_bsc(nat, msg) != 0) {
322 fprintf(stderr, "Should have not found aynthing.\n");
323 abort();
324 }
325 talloc_free(parsed);
326
327 /* Test by finding it */
328 con->lac = 8213;
329 copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
330 parsed = bsc_nat_parse(msg);
331 if (bsc_nat_find_bsc(nat, msg) != con) {
332 fprintf(stderr, "Should have found it.\n");
333 abort();
334 }
335 talloc_free(parsed);
336}
337
Holger Hans Peter Freyther465313e2010-06-15 18:49:53 +0800338static void test_mgcp(void)
339{
340 struct sccp_connections con;
341 struct bsc_nat_parsed *parsed;
342 struct msgb *msg;
343
344 fprintf(stderr, "Testing MGCP.\n");
345 memset(&con, 0, sizeof(con));
346
347 msg = msgb_alloc(4096, "foo");
348 copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
349 parsed = bsc_nat_parse(msg);
350 if (bsc_mgcp_assign(&con, msg) != 0) {
351 fprintf(stderr, "Failed to handle assignment.\n");
352 abort();
353 }
354
355 if (con.msc_timeslot != 21) {
356 fprintf(stderr, "Timeslot should be 21.\n");
357 abort();
358 }
359
360 if (con.bsc_timeslot != 21) {
361 fprintf(stderr, "Assigned timeslot should have been 21.\n");
362 abort();
363 }
364 talloc_free(parsed);
365
366 bsc_mgcp_clear(&con);
367 if (con.bsc_timeslot != -1 || con.msc_timeslot != -1) {
368 fprintf(stderr, "Clearing should remove the mapping.\n");
369 abort();
370 }
371}
372
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800373int main(int argc, char **argv)
374{
375 struct debug_target *stderr_target;
376
377 stderr_target = debug_target_create_stderr();
378 debug_add_target(stderr_target);
379 debug_set_all_filter(stderr_target, 1);
380
381 test_filter();
Holger Hans Peter Freyther04fd9922010-03-30 06:51:53 +0200382 test_contrack();
Holger Hans Peter Freyther04fd9922010-03-30 06:51:53 +0200383 test_paging();
Holger Hans Peter Freyther465313e2010-06-15 18:49:53 +0800384 test_mgcp();
Holger Hans Peter Freyther0b8f69d2010-06-15 18:45:38 +0800385 return 0;
386}
Holger Hans Peter Freyther38f7c752010-06-15 18:48:36 +0800387
388void input_event()
389{}
390int nm_state_event()
391{
392 return -1;
393}
394
395int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
396{
397 return -1;
398}