blob: 3b9ef4ed5b3fa8cda3c7d4b8ea1aae182efa2315 [file] [log] [blame]
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +02001/*
2 * SCCP testing code
3 *
4 * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freyther6ae65722010-02-03 18:10:07 +01005 * (C) 2009 by On-Waves
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +02006 *
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#include <stdio.h>
26
27#include <arpa/inet.h>
28
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020029#include <openbsc/gsm_data.h>
30#include <openbsc/debug.h>
Harald Weltef98a4972010-02-20 17:29:27 +010031#include <osmocore/msgb.h>
Holger Hans Peter Freyther8a69cb22010-02-12 22:44:50 +010032
33#include <sccp/sccp.h>
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020034
35#define MIN(x, y) ((x) < (y) ? (x) : (y))
36
37/* BSC -> MSC */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080038static const uint8_t bssmap_reset[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020039 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
40 0x02, 0x42, 0xfe, 0x06, 0x00, 0x04, 0x30, 0x04,
41 0x01, 0x20,
42};
43
44/* MSC -> BSC reset ack */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080045static const uint8_t bssmap_reset_ack[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020046 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
47 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x03,
48 0x00, 0x01, 0x31,
49};
50
51/* MSC -> BSC paging, connection less */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080052static const uint8_t bssmap_paging[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020053 0x09, 0x00, 0x03, 0x07, 0x0b, 0x04, 0x43, 0x01,
54 0x00, 0xfe, 0x04, 0x43, 0x5c, 0x00, 0xfe, 0x10,
55 0x00, 0x0e, 0x52, 0x08, 0x08, 0x29, 0x47, 0x10,
56 0x02, 0x01, 0x31, 0x97, 0x61, 0x1a, 0x01, 0x06,
57};
58
59/* MSC -> BSC paging, UDT without PC */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080060static const uint8_t bssmap_udt[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020061 0x09, 0x00, 0x03, 0x05, 0x07, 0x02, 0x42, 0xfe,
62 0x02, 0x42, 0xfe, 0x10, 0x00, 0x0e, 0x52, 0x08,
63 0x08, 0x29, 0x47, 0x10, 0x02, 0x01, 0x31, 0x97,
64 0x61, 0x1a, 0x01, 0x06,
65};
66
67/* BSC -> MSC connection open */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080068static const uint8_t bssmap_cr[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020069 0x01, 0x01, 0x02, 0x03, 0x02, 0x02, 0x04, 0x02,
70 0x42, 0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05,
71 0x08, 0x00, 0x72, 0xf4, 0x80, 0x20, 0x12, 0xc3,
72 0x50, 0x17, 0x10, 0x05, 0x24, 0x11, 0x03, 0x33,
73 0x19, 0xa2, 0x08, 0x29, 0x47, 0x10, 0x02, 0x01,
74 0x31, 0x97, 0x61, 0x00
75};
76
77/* MSC -> BSC connection confirm */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080078static const uint8_t bssmap_cc[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020079 0x02, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
80};
81
82/* MSC -> BSC DTAP
83 *
84 * we fake a bit and make it BSC -> MSC... so the
85 * payload does not make any sense..
86 */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080087static const uint8_t bssmap_dtap[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020088 0x06, 0x00, 0x00, 0x03, 0x00, 0x01, 0x0f, 0x01, 0x00, 0x0c,
89 0x03, 0x05, 0x5c, 0x08, 0x11, 0x81, 0x33, 0x66, 0x02, 0x13,
90 0x45, 0xf4,
91};
92
93/* MSC -> BSC clear command */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +080094static const uint8_t bssmap_clear[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +020095 0x06, 0x00, 0x00, 0x03, 0x00, 0x01, 0x06, 0x00, 0x04, 0x20,
96 0x04, 0x01, 0x09,
97};
98
99/* MSC -> BSC released */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800100static const uint8_t bssmap_released[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200101 0x04, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x01, 0x0f,
102 0x02, 0x23, 0x42, 0x00,
103};
104
105/* BSC -> MSC released */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800106static const uint8_t bssmap_release_complete[] = {
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200107 0x05, 0x01, 0x02, 0x03, 0x00, 0x00, 0x03
108};
109
110struct test_data {
111 int length;
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800112 const uint8_t *data;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200113 int payload_start;
114 int payload_length;
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800115 uint8_t first_byte;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200116
117 /* in case it should trigger a sccp response */
118 int write;
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800119 const uint8_t *response;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200120 int response_length;
121};
122
123static const struct test_data test_data[] = {
124 {
125 .length = ARRAY_SIZE(bssmap_reset),
126 .data = &bssmap_reset[0],
127 .payload_start = 12,
128 .payload_length = ARRAY_SIZE(bssmap_reset) - 12,
129 .first_byte = 0x0,
130 },
131 {
132 .length = ARRAY_SIZE(bssmap_reset_ack),
133 .data = &bssmap_reset_ack[0],
134 .payload_start = 16,
135 .payload_length = ARRAY_SIZE(bssmap_reset_ack) - 16,
136 .first_byte = 0x0,
137 },
138 {
139 .length = ARRAY_SIZE(bssmap_paging),
140 .data = &bssmap_paging[0],
141 .payload_start = 16,
142 .payload_length = ARRAY_SIZE(bssmap_paging) - 16,
143 .first_byte = 0x0,
144 },
145 {
146 .length = ARRAY_SIZE(bssmap_cr),
147 .data = &bssmap_cr[0],
148 .payload_start = 12,
149 /* 0x00 is end of optional data, subtract this byte */
150 .payload_length = 31,
151 .first_byte = 0x0,
152
153 /* the connection request should trigger a connection confirm */
154 .write = 1,
155 .response = &bssmap_cc[0],
156 .response_length= ARRAY_SIZE(bssmap_cc),
157 },
158 {
159 .length = ARRAY_SIZE(bssmap_dtap),
160 .data = &bssmap_dtap[0],
161 .payload_start = 7,
162 .payload_length = 15,
163 .first_byte = 0x01,
164 },
165 {
166 .length = ARRAY_SIZE(bssmap_clear),
167 .data = &bssmap_clear[0],
168 .payload_start = 7,
169 .payload_length = 6,
170 .first_byte = 0x00,
171 },
172 {
173 .length = ARRAY_SIZE(bssmap_released),
174 .data = &bssmap_released[0],
175 .payload_length = 2,
176 .payload_start = 11,
177 .first_byte = 0x23,
178
179 .write = 1,
180 .response = &bssmap_release_complete[0],
181 .response_length= ARRAY_SIZE(bssmap_release_complete),
182 },
183};
184
185/* we will send UDTs and verify they look like this */
186static const struct test_data send_data[] = {
187 {
188 .length = ARRAY_SIZE(bssmap_udt),
189 .data = &bssmap_udt[0],
190 .payload_start = 12,
191 .payload_length = ARRAY_SIZE(bssmap_udt) - 12,
192 .first_byte = 0x0,
193 },
194 {
195 .length = ARRAY_SIZE(bssmap_reset),
196 .data = &bssmap_reset[0],
197 .payload_start = 12,
198 .payload_length = ARRAY_SIZE(bssmap_reset) - 12,
199 .first_byte = 0x0,
200 },
201};
202
203struct connection_test {
204 /* should the connection be refused? */
205 int refuse;
206
207 int with_data;
208
209 /* on which side to close the connection? */
210 int close_side;
211 int close_cause;
212};
213
214/* sccp connection handling we want to test */
215static const struct connection_test connection_tests[] = {
216 {
217 .refuse = 1,
218 },
219 {
220 .refuse = 1,
221 .with_data = 1,
222 },
223 {
224 .refuse = 0,
225 .close_side = 0,
226 .close_cause = 5,
227 },
228 {
229 .refuse = 0,
230 .close_side = 0,
231 .close_cause = 5,
232 .with_data = 1,
233 },
234 {
235 .refuse = 0,
236 .close_side = 1,
237 .close_cause = 5,
238 },
239 {
240 .refuse = 0,
241 .close_side = 1,
242 .close_cause = 5,
243 .with_data = 1,
244 },
245};
246
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100247struct sccp_parse_header_result {
248 /* results */
249 int msg_type;
250 int wanted_len;
251 int src_ssn;
252 int dst_ssn;
253
254 int has_src_ref, has_dst_ref;
255 struct sccp_source_reference src_ref;
256 struct sccp_source_reference dst_ref;
257
258 /* the input */
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800259 const uint8_t *input;
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100260 int input_len;
261};
262
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800263static const uint8_t it_test[] = {
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +01002640x10, 0x01, 0x07,
2650x94, 0x01, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 };
266
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800267static const uint8_t proto_err[] = {
Holger Hans Peter Freyther2cdda722010-04-21 15:38:16 +08002680x0f, 0x0c, 0x04, 0x00, 0x00,
269};
270
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100271static const struct sccp_parse_header_result parse_result[] = {
272 {
273 .msg_type = SCCP_MSG_TYPE_IT,
274 .wanted_len = 0,
275 .src_ssn = -1,
276 .dst_ssn = -1,
277 .has_src_ref = 1,
278 .has_dst_ref = 1,
279
280 .src_ref = {
281 .octet1 = 0x01,
282 .octet2 = 0x04,
283 .octet3 = 0x00
284 },
285 .dst_ref = {
286 .octet1 = 0x01,
287 .octet2 = 0x07,
288 .octet3 = 0x94,
289 },
290
291 .input = it_test,
292 .input_len = sizeof(it_test),
293 },
Holger Hans Peter Freyther2cdda722010-04-21 15:38:16 +0800294 {
295 .msg_type = SCCP_MSG_TYPE_ERR,
296 .wanted_len = 0,
297 .src_ssn = -1,
298 .dst_ssn = -1,
299 .has_src_ref = 0,
300 .has_dst_ref = 1,
301 .dst_ref = {
302 .octet1 = 0x0c,
303 .octet2 = 0x04,
304 .octet3 = 0x00,
305 },
306 .input = proto_err,
307 .input_len = sizeof(proto_err),
308 },
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100309};
310
311
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200312/* testing procedure:
313 * - we will use sccp_write and see what will be set in the
314 * outgoing callback
315 * - we will call sccp_system_incoming and see which calls
316 * are made. And then compare it to the ones we expect. We
317 * want the payload to arrive, or callbacks to be called.
318 * - we will use sccp_connection_socket and sccp_connection_write
319 * and verify state handling of connections
320 */
321
322static int current_test;
323
324/*
325 * test state...
326 */
327static int called = 0;
328static int matched = 0;
329static int write_called = 0;
330
331#define FAIL(x, args...) printf("FAILURE in %s:%d: " x, __FILE__, __LINE__, ## args)
332
333/*
334 * writing these packets and expecting a result
335 */
336int sccp_read_cb(struct msgb *data, unsigned len, void *context)
337{
Holger Hans Peter Freytherf9570952010-07-23 18:39:39 +0800338 uint16_t payload_length = test_data[current_test].payload_length;
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800339 const uint8_t *got, *wanted;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200340 int i;
341
342 called = 1;
343
344 if (msgb_l3len(data) < len) {
345 /* this should never be reached */
346 FAIL("Something horrible happened.. invalid packet..\n");
347 exit(-1);
348 }
349
350 if (len == 0 || len != payload_length) {
351 FAIL("length mismatch: got: %d wanted: %d\n", msgb_l3len(data), payload_length);
352 return -1;
353 }
354
355 if (data->l3h[0] != test_data[current_test].first_byte) {
356 FAIL("The first bytes of l3 do not match: 0x%x 0x%x\n",
357 data->l3h[0], test_data[current_test].first_byte);
358 return -1;
359 }
360
361 got = &data->l3h[0];
362 wanted = test_data[current_test].data + test_data[current_test].payload_start;
363
364 for (i = 0; i < len; ++i) {
365 if (got[i] != wanted[i]) {
366 FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n",
367 got[i], wanted[i], i);
368 return -1;
369 }
370 }
371
372 matched = 1;
373 return 0;
374}
375
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100376void sccp_write_cb(struct msgb *data, void *ctx)
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200377{
378 int i = 0;
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800379 const uint8_t *got, *wanted;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200380
381 if (test_data[current_test].response == NULL) {
382 FAIL("Didn't expect write callback\n");
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100383 goto exit;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200384 } else if (test_data[current_test].response_length != msgb_l2len(data)) {
385 FAIL("Size does not match. Got: %d Wanted: %d\n",
386 msgb_l2len(data), test_data[current_test].response_length);
387 }
388
389 got = &data->l2h[0];
390 wanted = test_data[current_test].response;
391
392 for (i = 0; i < msgb_l2len(data); ++i) {
393 if (got[i] != wanted[i]) {
394 FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n",
395 got[i], wanted[i], i);
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100396 goto exit;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200397 }
398 }
399
400 write_called = 1;
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100401
402exit:
403 msgb_free(data);
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200404}
405
406void sccp_c_read(struct sccp_connection *connection, struct msgb *msgb, unsigned int len)
407{
408 sccp_read_cb(msgb, len, connection->data_ctx);
409}
410
411void sccp_c_state(struct sccp_connection *connection, int old_state)
412{
413 if (connection->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE)
414 sccp_connection_free(connection);
415}
416
417int sccp_accept_cb(struct sccp_connection *connection, void *user_data)
418{
419 called = 1;
420 unsigned int ref = 0;
421 ref |= connection->destination_local_reference.octet1 << 24;
422 ref |= connection->destination_local_reference.octet2 << 16;
423 ref |= connection->destination_local_reference.octet3 << 8;
424 ref = ntohl(ref);
425
426 connection->data_cb = sccp_c_read;
427 connection->state_cb = sccp_c_state;
428
429 /* accept this */
430 return 0;
431}
432
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100433static void sccp_udt_write_cb(struct msgb *data, void *context)
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200434{
Holger Hans Peter Freytherc2c46212010-07-23 18:39:17 +0800435 const uint8_t *got, *wanted;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200436 int i;
437
438 write_called = 1;
439
440 if (send_data[current_test].length != msgb_l2len(data)) {
441 FAIL("Size does not match. Got: %d Wanted: %d\n",
442 msgb_l2len(data), send_data[current_test].length);
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100443 goto exit;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200444 }
445
446 got = &data->l2h[0];
447 wanted = send_data[current_test].data;
448
449 for (i = 0; i < msgb_l2len(data); ++i) {
450 if (got[i] != wanted[i]) {
451 FAIL("Failed to compare byte. Got: 0x%x Wanted: 0x%x at %d\n",
452 got[i], wanted[i], i);
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100453 goto exit;
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200454 }
455 }
456
457 matched = 1;
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100458
459exit:
460 msgb_free(data);
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200461}
462
463static void test_sccp_system(void)
464{
465 sccp_system_init(sccp_write_cb, NULL);
466 sccp_set_read(&sccp_ssn_bssap, sccp_read_cb, NULL);
467 sccp_connection_set_incoming(&sccp_ssn_bssap, sccp_accept_cb, NULL);
468
469 for (current_test = 0; current_test < ARRAY_SIZE(test_data); ++current_test) {
470 unsigned int length = test_data[current_test].length;
471 struct msgb *msg = msgb_alloc_headroom(length + 2, 2, __func__);
472 msg->l2h = msgb_put(msg, length);
473 memcpy(msg->l2h, test_data[current_test].data, length);
474
475 called = matched = write_called = 0;
476 printf("Testing packet: %d\n", current_test);
477 sccp_system_incoming(msg);
478
479 if (!called || !matched || (test_data[current_test].write != write_called))
480 FAIL("current test: %d called: %d matched: %d write: %d\n",
481 current_test, called, matched, write_called);
482
483 msgb_free(msg);
484 }
485}
486
487/* test sending of udt */
488static void test_sccp_send_udt(void)
489{
490 sccp_system_init(sccp_udt_write_cb, NULL);
491 sccp_set_read(NULL, NULL, NULL);
492 sccp_connection_set_incoming(NULL, NULL, NULL);
493
494 for (current_test = 0; current_test < ARRAY_SIZE(send_data); ++current_test) {
495 const struct test_data *test = &send_data[current_test];
496
497 struct msgb *msg = msgb_alloc(test->payload_length, __func__);
498 msg->l3h = msgb_put(msg, test->payload_length);
499 memcpy(msg->l3h, test->data + test->payload_start, test->payload_length);
500
501 matched = write_called = 0;
502 printf("Testing packet: %d\n", current_test);
503 sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
504
505 if (!matched || !write_called)
506 FAIL("current test: %d matched: %d write: %d\n",
507 current_test, matched, write_called);
508
509 msgb_free(msg);
510 }
511}
512
513/* send udt from one end to another */
514static unsigned int test_value = 0x2442;
515static int sccp_udt_read(struct msgb *data, unsigned int len, void *context)
516{
517 unsigned int *val;
518
519 if (len != 4) {
520 FAIL("Wrong size: %d\n", msgb_l3len(data));
521 return -1;
522 }
523
524 val = (unsigned int*)data->l3h;
525 matched = test_value == *val;
526
527 return 0;
528}
529
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100530static void sccp_write_loop(struct msgb *data, void *context)
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200531{
532 /* send it back to us */
533 sccp_system_incoming(data);
Holger Hans Peter Freyther3c1221e2010-03-26 05:44:21 +0100534 msgb_free(data);
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200535}
536
537static void test_sccp_udt_communication(void)
538{
539 struct msgb *data;
540 unsigned int *val;
541
542 sccp_system_init(sccp_write_loop, NULL);
543 sccp_set_read(&sccp_ssn_bssap, sccp_udt_read, NULL);
544 sccp_connection_set_incoming(NULL, NULL, NULL);
545
546
547 data = msgb_alloc(4, "test data");
548 data->l3h = &data->data[0];
549 val = (unsigned int *)msgb_put(data, 4);
550 *val = test_value;
551
552 matched = 0;
553 sccp_write(data, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
554
555 if (!matched)
556 FAIL("Talking with us didn't work\n");
557
558 msgb_free(data);
559}
560
561
562/* connection testing... open, send, close */
563static const struct connection_test *current_con_test;
564static struct sccp_connection *outgoing_con;
565static struct sccp_connection *incoming_con;
566static int outgoing_data, incoming_data, incoming_state, outgoing_state;
567
568static struct msgb *test_data1, *test_data2, *test_data3;
569
570static void sccp_conn_in_state(struct sccp_connection *conn, int old_state)
571{
572 printf("\tincome: %d -> %d\n", old_state, conn->connection_state);
573 if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
574 if (conn == incoming_con) {
575 sccp_connection_free(conn);
576 incoming_con = NULL;
577 }
578 }
579}
580
581static void sccp_conn_in_data(struct sccp_connection *conn, struct msgb *msg, unsigned int len)
582{
583 /* compare the data */
584 ++incoming_data;
585 printf("\tincoming data: %d\n", len);
586
587 /* compare the data */
588 if (len != 4) {
589 FAIL("Length of packet is wrong: %u %u\n", msgb_l3len(msg), len);
590 return;
591 }
592
593 if (incoming_data == 1) {
594 if (memcmp(msg->l3h, test_data1->l3h, len) != 0) {
595 FAIL("Comparing the data failed: %d\n", incoming_data);
596 incoming_state = 0;
597 printf("Got: %s\n", hexdump(msg->l3h, len));
598 printf("Wanted: %s\n", hexdump(test_data1->l3h, len));
599
600 }
601 } else if (incoming_data == 2) {
602 if (memcmp(msg->l3h, test_data2->l3h, len) != 0) {
603 FAIL("Comparing the data failed: %d\n", incoming_data);
604 incoming_state = 0;
605 printf("Got: %s\n", hexdump(msg->l3h, len));
606 printf("Wanted: %s\n", hexdump(test_data2->l3h, len));
607 }
608 }
609
610 /* sending out data */
611 if (incoming_data == 2) {
612 printf("\tReturning data3\n");
613 sccp_connection_write(conn, test_data3);
614 }
615}
616
617static int sccp_conn_accept(struct sccp_connection *conn, void *ctx)
618{
619 printf("\taccept: %p\n", conn);
620 conn->state_cb = sccp_conn_in_state;
621 conn->data_cb = sccp_conn_in_data;
622
623 if (current_con_test->refuse)
624 return -1;
625
626 incoming_con = conn;
627 return 0;
628}
629
630/* callbacks for the outgoing side */
631static void sccp_conn_out_state(struct sccp_connection *conn, int old_state)
632{
633 printf("\toutgoing: %p %d -> %d\n", conn, old_state, conn->connection_state);
634
635 if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
636 if (conn == outgoing_con) {
637 sccp_connection_free(conn);
638 outgoing_con = NULL;
639 }
640 }
641}
642
643static void sccp_conn_out_data(struct sccp_connection *conn, struct msgb *msg, unsigned int len)
644{
645 ++outgoing_data;
646 printf("\toutgoing data: %p %d\n", conn, len);
647
648 if (len != 4)
649 FAIL("Length of packet is wrong: %u %u\n", msgb_l3len(msg), len);
650
651 if (outgoing_data == 1) {
652 if (memcmp(msg->l3h, test_data3->l3h, len) != 0) {
653 FAIL("Comparing the data failed\n");
654 outgoing_state = 0;
655 }
656 }
657}
658
659static void do_test_sccp_connection(const struct connection_test *test)
660{
661 int ret;
662
663 current_con_test = test;
664 outgoing_con = incoming_con = 0;
665
666 outgoing_con = sccp_connection_socket();
667 if (!outgoing_con) {
668 FAIL("Connection is NULL\n");
669 return;
670 }
671
672 outgoing_con->state_cb = sccp_conn_out_state;
673 outgoing_con->data_cb = sccp_conn_out_data;
674 outgoing_data = incoming_data = 0;
675 incoming_state = outgoing_state = 1;
676
677 /* start testing */
678 if (test->with_data) {
679 if (sccp_connection_connect(outgoing_con, &sccp_ssn_bssap, test_data1) != 0)
680 FAIL("Binding failed\n");
681 } else {
682 ++incoming_data;
683 if (sccp_connection_connect(outgoing_con, &sccp_ssn_bssap, NULL) != 0)
684 FAIL("Binding failed\n");
685 }
686
687 if (test->refuse) {
688 if (outgoing_con)
689 FAIL("Outgoing connection should have been refused.\n");
690 } else {
691 if (!incoming_con)
692 FAIL("Creating incoming didn't work.\n");
693
694 printf("\tWriting test data2\n");
695 sccp_connection_write(outgoing_con, test_data2);
Holger Hans Peter Freyther3b9516e2009-11-18 22:11:28 +0100696 sccp_connection_send_it(outgoing_con);
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200697
698 /* closing connection */
699 if (test->close_side == 0)
700 ret = sccp_connection_close(outgoing_con, 0);
701 else
702 ret = sccp_connection_close(incoming_con, 0);
703
704 if (ret != 0)
705 FAIL("Closing the connection failed\n");
706 }
707
708 /* outgoing should be gone now */
709 if (outgoing_con)
710 FAIL("Outgoing connection was not properly closed\n");
711
712 if (incoming_con)
713 FAIL("Incoming connection was not propery closed.\n");
714
715 if (test->refuse == 0) {
716 if (outgoing_data != 1 || incoming_data != 2) {
717 FAIL("Data sending failed: %d/%d %d/%d\n",
718 outgoing_data, 1,
719 incoming_data, 2);
720 }
721 }
722
723 if (!incoming_state || !outgoing_state)
724 FAIL("Failure with the state transition. %d %d\n",
725 outgoing_state, incoming_state);
726}
727
728static void test_sccp_connection(void)
729{
730 sccp_system_init(sccp_write_loop, NULL);
731 sccp_set_read(NULL, NULL, NULL);
732 sccp_connection_set_incoming(&sccp_ssn_bssap, sccp_conn_accept, NULL);
733
734 test_data1 = msgb_alloc(4, "data1");
735 test_data1->l3h = msgb_put(test_data1, 4);
736 *((unsigned int*)test_data1->l3h) = 0x23421122;
737
738 test_data2 = msgb_alloc(4, "data2");
739 test_data2->l3h = msgb_put(test_data2, 4);
740 *((unsigned int*)test_data2->l3h) = 0x42232211;
741
742 test_data3 = msgb_alloc(4, "data3");
743 test_data3->l3h = msgb_put(test_data3, 4);
744 *((unsigned int*)test_data3->l3h) = 0x2323ff55;
745
746
747 for (current_test = 0; current_test < ARRAY_SIZE(connection_tests); ++current_test) {
748 printf("Testing %d refuse: %d with_data: %d\n",
749 current_test, connection_tests[current_test].refuse,
750 connection_tests[current_test].with_data);
751 do_test_sccp_connection(&connection_tests[current_test]);
752 }
753
754 msgb_free(test_data1);
755 msgb_free(test_data2);
756 msgb_free(test_data3);
757}
758
759/* invalid input */
760static void test_sccp_system_crash(void)
761{
762 printf("trying to provoke a crash with invalid input\n");
763 sccp_set_read(&sccp_ssn_bssap, sccp_read_cb, NULL);
764 sccp_connection_set_incoming(&sccp_ssn_bssap, sccp_accept_cb, NULL);
765
766 for (current_test = 0; current_test < ARRAY_SIZE(test_data); ++current_test) {
767 int original_length = test_data[current_test].length;
768 int length = original_length + 2;
769 int i;
770
771 printf("Testing packet: %d\n", current_test);
772
773 for (i = length; i >= 0; --i) {
774 unsigned int length = MIN(test_data[current_test].length, i);
775 struct msgb *msg = msgb_alloc_headroom(length + 2, 2, __func__);
776 msg->l2h = msgb_put(msg, length);
777 memcpy(msg->l2h, test_data[current_test].data, length);
778 sccp_system_incoming(msg);
779 msgb_free(msg);
780 }
781 }
782
783 printf("survived\n");
784}
785
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100786static void test_sccp_parsing(void)
787{
788 for (current_test = 0; current_test < ARRAY_SIZE(parse_result); ++current_test) {
789 struct msgb *msg;
790 struct sccp_parse_result result;
791
792 msg = msgb_alloc_headroom(1024, 128, "parse-test");
793 msgb_put(msg, 1);
794 msg->l2h = msgb_put(msg, parse_result[current_test].input_len);
795 memcpy(msg->l2h, parse_result[current_test].input, msgb_l2len(msg));
796
797 memset(&result, 0, sizeof(result));
798 if (sccp_parse_header(msg, &result) != 0) {
Holger Hans Peter Freyther2cdda722010-04-21 15:38:16 +0800799 fprintf(stderr, "Failed to sccp parse test: %d\n", current_test);
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100800 } else {
801 if (parse_result[current_test].wanted_len != result.data_len) {
802 fprintf(stderr, "Unexpected data length.\n");
803 abort();
804 }
805
806 if (parse_result[current_test].has_src_ref) {
807 if (memcmp(result.source_local_reference,
808 &parse_result[current_test].src_ref,
809 sizeof(struct sccp_source_reference)) != 0) {
810 fprintf(stderr, "SRC REF did not match\n");
811 abort();
812 }
813 }
814
815 if (parse_result[current_test].has_dst_ref) {
816 if (memcmp(result.destination_local_reference,
817 &parse_result[current_test].dst_ref,
818 sizeof(struct sccp_source_reference)) != 0) {
819 fprintf(stderr, "DST REF did not match\n");
820 abort();
821 }
822 }
823
824 if (parse_result[current_test].src_ssn != -1) {
825 fprintf(stderr, "Not implemented.\n");
826 abort();
827 }
828
829 if (parse_result[current_test].dst_ssn != -1) {
830 fprintf(stderr, "Not implemented.\n");
831 abort();
832 }
833 }
834
835 msgb_free(msg);
836 }
837}
838
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200839
840int main(int argc, char **argv)
841{
842 test_sccp_system();
843 test_sccp_send_udt();
844 test_sccp_udt_communication();
845 test_sccp_connection();
846 test_sccp_system_crash();
Holger Hans Peter Freythere1d50672010-02-26 19:26:35 +0100847 test_sccp_parsing();
Holger Hans Peter Freytherac967702009-07-29 07:37:48 +0200848 return 0;
849}
Holger Hans Peter Freyther5dbd71e2009-12-23 05:13:48 +0100850
851void db_store_counter() {}