blob: 7d5d06968f6a6b1d9e2c177def0f4d396897e5ac [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/*
2 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Nico Golde28de0532010-07-09 17:19:12 +02003 * (C) 2010 by Nico Golde <nico@ngolde.de>
Alexander Chemeris93d9a192014-03-07 20:55:21 +01004 * (C) 2014 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
Harald Welteec8b4502010-02-20 20:34:29 +01005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
Holger Hans Peter Freyther4d7e49b2013-05-02 22:37:16 +020026
27#include <osmocom/gsm/protocol/gsm_03_40.h>
Alexander Chemeris93d9a192014-03-07 20:55:21 +010028#include <osmocom/gsm/protocol/gsm_04_11.h>
Holger Hans Peter Freyther4d7e49b2013-05-02 22:37:16 +020029
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010030#include <osmocom/gsm/gsm_utils.h>
Holger Hans Peter Freyther4d7e49b2013-05-02 22:37:16 +020031#include <osmocom/gsm/gsm0411_utils.h>
32
33#include <osmocom/core/msgb.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010034#include <osmocom/core/utils.h>
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080035
Alexander Chemerisf6248612014-03-07 20:42:03 +010036#include <osmocom/core/logging.h>
37#include <osmocom/core/application.h>
38
39struct log_info fake_log_info = {};
40
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080041struct test_case {
42 const uint8_t *input;
43 const uint16_t input_length;
44
45 const uint8_t *expected;
Dennis Wehrle291e6132011-07-24 20:14:13 +020046 const uint16_t expected_octet_length;
47 const uint16_t expected_septet_length;
48 const uint8_t ud_hdr_ind;
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080049};
50
51static const char simple_text[] = "test text";
Dennis Wehrle291e6132011-07-24 20:14:13 +020052#define simple_septet_length 9
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080053static const uint8_t simple_enc[] = {
Nico Goldec0ce9aa2010-07-20 15:43:58 +020054 0xf4, 0xf2, 0x9c, 0x0e, 0xa2, 0x97, 0xf1, 0x74
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080055};
56
Dennis Wehrle291e6132011-07-24 20:14:13 +020057static const char escape_text[] = "!$ a more#^- complicated test@@?_%! case";
58#define escape_septet_length 41 /* note: the ^ counts as two, because it is a extension character */
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080059static const uint8_t escape_enc[] = {
60 0x21, 0x01, 0x28, 0x0c, 0x6a, 0xbf, 0xe5, 0xe5, 0xd1,
61 0x86, 0xd2, 0x02, 0x8d, 0xdf, 0x6d, 0x38, 0x3b, 0x3d,
62 0x0e, 0xd3, 0xcb, 0x64, 0x10, 0xbd, 0x3c, 0xa7, 0x03,
63 0x00, 0xbf, 0x48, 0x29, 0x04, 0x1a, 0x87, 0xe7, 0x65,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +080064};
65
Dennis Wehrle291e6132011-07-24 20:14:13 +020066static const char enhanced_text[] = "enhanced ^ {][} test |+~ ^ test";
67#define enhanced_septet_length 39 /* note: the characters { } [ ] ^ | ~ count as two (each of them), because they are extension characters */
68static const uint8_t enhanced_enc[] = {
69 0x65, 0x37, 0x3A, 0xEC, 0x1E, 0x97, 0xC9, 0xA0, 0x0D,
70 0x05, 0xB4, 0x41, 0x6D, 0x7C, 0x1B, 0xDE, 0x26, 0x05,
71 0xA2, 0x97, 0xE7, 0x74, 0xD0, 0x06, 0xB8, 0xDA, 0xF4,
72 0x40, 0x1B, 0x0A, 0x88, 0x5E, 0x9E, 0xD3, 0x01,
73};
74
75static const char enhancedV2_text[] = "enhanced ^ {][} test |+~ ^ tests";
76#define enhancedV2_septet_length 40 /* note: number of octets are equal to the enhanced_text! */
77static const uint8_t enhancedV2_enc[] = {
78 0x65, 0x37, 0x3A, 0xEC, 0x1E, 0x97, 0xC9, 0xA0, 0x0D,
79 0x05, 0xB4, 0x41, 0x6D, 0x7C, 0x1B, 0xDE, 0x26, 0x05,
80 0xA2, 0x97, 0xE7, 0x74, 0xD0, 0x06, 0xB8, 0xDA, 0xF4,
81 0x40, 0x1B, 0x0A, 0x88, 0x5E, 0x9E, 0xD3, 0xE7,
82};
83
84
85
86static const char concatenated_text[] =
87 "this is a testmessage. this is a testmessage. this is a testmessage. this is a testmessage. "
88 "this is a testmessage. this is a testmessage. cut here .....: this is a second testmessage. end here.";
89
90static const char splitted_text_part1[] =
91 "this is a testmessage. this is a testmessage. this is a testmessage. this is a testmessage. "
92 "this is a testmessage. this is a testmessage. cut here .....:";
93#define concatenated_part1_septet_length_with_header 160
94#define concatenated_part1_septet_length 153
95static const uint8_t concatenated_part1_enc[] = {
96 0x05, 0x00, 0x03, 0x6f, 0x02, 0x01,
97 0xe8, 0xe8, 0xf4, 0x1c, 0x94, 0x9e, 0x83, 0xc2,
98 0x20, 0x7a, 0x79, 0x4e, 0x6f, 0x97, 0xe7, 0xf3,
99 0xf0, 0xb9, 0xec, 0x02, 0xd1, 0xd1, 0xe9, 0x39,
100 0x28, 0x3d, 0x07, 0x85, 0x41, 0xf4, 0xf2, 0x9c,
101 0xde, 0x2e, 0xcf, 0xe7, 0xe1, 0x73, 0xd9, 0x05,
102 0xa2, 0xa3, 0xd3, 0x73, 0x50, 0x7a, 0x0e, 0x0a,
103 0x83, 0xe8, 0xe5, 0x39, 0xbd, 0x5d, 0x9e, 0xcf,
104 0xc3, 0xe7, 0xb2, 0x0b, 0x44, 0x47, 0xa7, 0xe7,
105 0xa0, 0xf4, 0x1c, 0x14, 0x06, 0xd1, 0xcb, 0x73,
106 0x7a, 0xbb, 0x3c, 0x9f, 0x87, 0xcf, 0x65, 0x17,
107 0x88, 0x8e, 0x4e, 0xcf, 0x41, 0xe9, 0x39, 0x28,
108 0x0c, 0xa2, 0x97, 0xe7, 0xf4, 0x76, 0x79, 0x3e,
109 0x0f, 0x9f, 0xcb, 0x2e, 0x10, 0x1d, 0x9d, 0x9e,
110 0x83, 0xd2, 0x73, 0x50, 0x18, 0x44, 0x2f, 0xcf,
111 0xe9, 0xed, 0xf2, 0x7c, 0x1e, 0x3e, 0x97, 0x5d,
112 0xa0, 0x71, 0x9d, 0x0e, 0x42, 0x97, 0xe5, 0x65,
113 0x90, 0xcb, 0xe5, 0x72, 0xb9, 0x74,
114};
115
116static const char splitted_text_part2[] = " this is a second testmessage. end here.";
117#define concatenated_part2_septet_length_with_header 47
118#define concatenated_part2_septet_length 40
119static const uint8_t concatenated_part2_enc[] = {
120 0x05, 0x00, 0x03, 0x6f, 0x02, 0x02,
121 0x40, 0x74, 0x74, 0x7a, 0x0e, 0x4a, 0xcf, 0x41,
122 0x61, 0xd0, 0xbc, 0x3c, 0x7e, 0xbb, 0xc9, 0x20,
123 0x7a, 0x79, 0x4e, 0x6f, 0x97, 0xe7, 0xf3, 0xf0,
124 0xb9, 0xec, 0x02, 0x95, 0xdd, 0x64, 0x10, 0xba,
125 0x2c, 0x2f, 0xbb, 0x00,
126};
127
128static const struct test_case test_multiple_encode[] =
129{
130 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200131 .input = (const uint8_t *) concatenated_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200132 .expected = concatenated_part1_enc,
133 .expected_octet_length = sizeof(concatenated_part1_enc),
134 .expected_septet_length = concatenated_part1_septet_length,
135 .ud_hdr_ind = 1,
136 },
137 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200138 .input = (const uint8_t *) concatenated_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200139 .expected = concatenated_part2_enc,
140 .expected_octet_length = sizeof(concatenated_part2_enc),
141 .expected_septet_length = concatenated_part2_septet_length,
142 .ud_hdr_ind = 1,
143 },
144};
145
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800146static const struct test_case test_encode[] =
147{
148 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200149 .input = (const uint8_t *) simple_text,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800150 .expected = simple_enc,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200151 .expected_octet_length = sizeof(simple_enc),
152 .expected_septet_length = simple_septet_length,
153 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800154 },
155 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200156 .input = (const uint8_t *) escape_text,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800157 .expected = escape_enc,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200158 .expected_octet_length = sizeof(escape_enc),
159 .expected_septet_length = escape_septet_length,
160 .ud_hdr_ind = 0,
161 },
162 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200163 .input = (const uint8_t *) enhanced_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200164 .expected = enhanced_enc,
165 .expected_octet_length = sizeof(enhanced_enc),
166 .expected_septet_length = enhanced_septet_length,
167 .ud_hdr_ind = 0,
168 },
169 {
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200170 .input = (const uint8_t *) enhancedV2_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200171 .expected = enhancedV2_enc,
172 .expected_octet_length = sizeof(enhancedV2_enc),
173 .expected_septet_length = enhancedV2_septet_length,
174 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800175 },
176};
177
178static const struct test_case test_decode[] =
179{
180 {
181 .input = simple_enc,
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200182 .input_length = sizeof(simple_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200183 .expected = (const uint8_t *) simple_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200184 .expected_septet_length = simple_septet_length,
185 .ud_hdr_ind = 0,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800186 },
187 {
188 .input = escape_enc,
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200189 .input_length = sizeof(escape_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200190 .expected = (const uint8_t *) escape_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200191 .expected_septet_length = escape_septet_length,
192 .ud_hdr_ind = 0,
193 },
194 {
195 .input = enhanced_enc,
196 .input_length = sizeof(enhanced_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200197 .expected = (const uint8_t *) enhanced_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200198 .expected_septet_length = enhanced_septet_length,
199 .ud_hdr_ind = 0,
200 },
201 {
202 .input = enhancedV2_enc,
203 .input_length = sizeof(enhancedV2_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200204 .expected = (const uint8_t *) enhancedV2_text,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200205 .expected_septet_length = enhancedV2_septet_length,
206 .ud_hdr_ind = 0,
207 },
208 {
209 .input = concatenated_part1_enc,
210 .input_length = sizeof(concatenated_part1_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200211 .expected = (const uint8_t *) splitted_text_part1,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200212 .expected_septet_length = concatenated_part1_septet_length_with_header,
213 .ud_hdr_ind = 1,
214 },
215 {
216 .input = concatenated_part2_enc,
217 .input_length = sizeof(concatenated_part2_enc),
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200218 .expected = (const uint8_t *) splitted_text_part2,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200219 .expected_septet_length = concatenated_part2_septet_length_with_header,
220 .ud_hdr_ind = 1,
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800221 },
222};
Harald Welteec8b4502010-02-20 20:34:29 +0100223
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200224static void test_octet_return()
225{
226 char out[256];
227 int oct, septets;
228
229 printf("Encoding some tests and printing number of septets/octets\n");
230
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200231 septets = gsm_7bit_encode_n((uint8_t *) out, sizeof(out), "test1234", &oct);
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200232 printf("SEPTETS: %d OCTETS: %d\n", septets, oct);
233
234 printf("Done\n");
235}
236
Holger Hans Peter Freyther4d7e49b2013-05-02 22:37:16 +0200237static void test_gen_oa(void)
238{
239 uint8_t oa[12];
240 int len;
241
242 printf("Testing gsm340_gen_oa\n");
243
244 /* first try... */
245 len = gsm340_gen_oa(oa, ARRAY_SIZE(oa), GSM340_TYPE_UNKNOWN,
246 GSM340_PLAN_ISDN, "12345678901234567891");
247 OSMO_ASSERT(len == 12);
248 printf("Result: len(%d) data(%s)\n", len, osmo_hexdump(oa, len));
249 len = gsm340_gen_oa(oa, ARRAY_SIZE(oa), GSM340_TYPE_NATIONAL,
250 GSM340_PLAN_ISDN, "12345678901234567891");
251 OSMO_ASSERT(len == 12);
252 printf("Result: len(%d) data(%s)\n", len, osmo_hexdump(oa, len));
253
254 /* long input.. will fail and just prints the header*/
255 len = gsm340_gen_oa(oa, ARRAY_SIZE(oa), GSM340_TYPE_INTERNATIONAL,
256 GSM340_PLAN_ISDN, "123456789123456789120");
257 OSMO_ASSERT(len == 2);
258 printf("Result: len(%d) data(%s)\n", len, osmo_hexdump(oa, len));
259
260 /* try the alpha numeric encoding */
261 len = gsm340_gen_oa(oa, ARRAY_SIZE(oa), GSM340_TYPE_ALPHA_NUMERIC,
262 GSM340_PLAN_UNKNOWN, "OpenBSC");
263 OSMO_ASSERT(len == 9);
264 printf("Result: len(%d) data(%s)\n", len, osmo_hexdump(oa, len));
265
266 /* long alpha numeric text */
267 len = gsm340_gen_oa(oa, ARRAY_SIZE(oa), GSM340_TYPE_ALPHA_NUMERIC,
268 GSM340_PLAN_UNKNOWN, "OpenBSCabcdefghijklm");
269 OSMO_ASSERT(len == 12);
270 printf("Result: len(%d) data(%s)\n", len, osmo_hexdump(oa, len));
271}
272
Alexander Chemeris93d9a192014-03-07 20:55:21 +0100273#define PRINT_VALIDITY_TIMES(expected, decoded) \
274{ \
275 char _validity_timestamp[1024]; \
276 time_t _temp_time; \
277 _temp_time = (expected); \
278 strftime(_validity_timestamp, sizeof(_validity_timestamp), \
279 "%F %T", gmtime(&_temp_time)); \
280 printf("Expected: %s\n", _validity_timestamp); \
281 _temp_time = (decoded); \
282 strftime(_validity_timestamp, sizeof(_validity_timestamp), \
283 "%F %T", gmtime(&_temp_time)); \
284 printf("Decoded: %s\n", _validity_timestamp); \
285} \
286
287#define TEST_VALIDITY_DECODING(test_data, encoding) \
288{ \
289 int i; \
290 time_t valid_until; \
291 for (i=0; i<ARRAY_SIZE(test_data); i++) \
292 { \
293 valid_until = gsm340_validity_time((test_data)[i].now, \
294 (encoding), (test_data)[i].vp); \
295 PRINT_VALIDITY_TIMES((test_data)[i].decoded, valid_until); \
296 OSMO_ASSERT(valid_until == (test_data)[i].decoded); \
297 } \
298}
299
300static void test_validity_period(void)
301{
302 time_t valid_until;
303 time_t vp_rel_default = SMS_DEFAULT_VALIDITY_PERIOD;
304
305 /* Relative data */
306 struct {
307 uint8_t vp[1];
308 time_t now;
309 time_t decoded;
310 } vp_rel_test[] = {
311 {{5}, 0, (5 + 1) * 5 * 60},
312 {{150}, 0, (12*60 + (150-143) * 30) * 60},
313 {{180}, 0, ((180 - 166) * 60 * 24) * 60},
314 {{250}, 0, ((250 - 192) * 60 * 24 * 7) * 60},
315 /* Non-zero 'now' value should accordingly shift the decoded value */
316 {{5}, 100, 100 + (5 + 1) * 5 * 60},
317 {{150}, 100, 100 + (12*60 + (150-143) * 30) * 60},
318 {{180}, 100, 100 + ((180 - 166) * 60 * 24) * 60},
319 {{250}, 100, 100 + ((250 - 192) * 60 * 24 * 7) * 60},
320 };
321
322 /* Absolute data */
323 struct {
324 uint8_t vp[8];
325 time_t now;
326 time_t decoded;
327 } vp_abs_test[] = {
328 /* 2013-05-15 12:24:36 UTC+0
329 * Basic check - no timezone offset, summer time, year after 2000 */
330 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 0, 1368620676},
331 /* 1984-05-15 12:24:36 UTC+0
332 * Test year before 2000 */
333 {{0x48, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 0, 453471876},
334 /* 2013-05-15 12:24:36 UTC+4
335 * Test positive timezone offset*/
336 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x61, 0x0}, 0, 1368606276},
337 /* 2013-12-24 12:24:36 UTC
338 * Test winter time */
339 {{0x31, 0x21, 0x42, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 0, 1387887876},
340 /* 2013-05-15 12:24:36 UTC-4
341 * Test negative timezone offset */
342 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x80|0x61, 0x0}, 0, 1368635076},
343 /* Adding current time should not change returned value, as it's absolute */
344 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 1000, 1368620676},
345 {{0x48, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 1000, 453471876},
346 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x00|0x61, 0x0}, 1000, 1368606276},
347 {{0x31, 0x21, 0x42, 0x21, 0x42, 0x63, 0x00|0x0, 0x0}, 1000, 1387887876},
348 {{0x31, 0x50, 0x51, 0x21, 0x42, 0x63, 0x80|0x61, 0x0}, 1000, 1368635076}
349 };
350
351 /* Enhanced data */
352 struct {
353 uint8_t vp[5];
354 time_t now;
355 time_t decoded;
356 } vp_enh_test[] = {
357 /* No Validity Period specified, no extension */
358 {{0x00, 0x00, 0x00, 0x00, 0x00}, 0, SMS_DEFAULT_VALIDITY_PERIOD},
359 /* Relative case, no extension */
360 {{0x01, 5, 0x00, 0x00, 0x00}, 0, (5 + 1) * 5 * 60},
361 {{0x01, 150, 0x00, 0x00, 0x00}, 0, (12*60 + (150-143) * 30) * 60},
362 {{0x01, 180, 0x00, 0x00, 0x00}, 0, ((180 - 166) * 60 * 24) * 60},
363 {{0x01, 250, 0x00, 0x00, 0x00}, 0, ((250 - 192) * 60 * 24 * 7) * 60},
364 /* Relative case, with extension */
365 {{0x81, 0x00, 5, 0x00, 0x00}, 0, (5 + 1) * 5 * 60},
366 /* Relative integer case, no extension */
367 {{0x02, 123, 0x00, 0x00, 0x00}, 0, 123},
368 /* Relative semioctet case, no extension
369 * 2:15:23 */
370 {{0x03, 0x20, 0x51, 0x32, 0x00}, 0, (2*60 + 15) * 60 + 23},
371 /* Unknown functionality indicator */
372 {{0x04, 0x00, 0x00, 0x00, 0x00}, 0, SMS_DEFAULT_VALIDITY_PERIOD},
373 /* Non-zero 'now' value should accordingly shift the decoded value */
374 {{0x00, 0x00, 0x00, 0x00, 0x00}, 1000, 1000 + SMS_DEFAULT_VALIDITY_PERIOD},
375 {{0x01, 5, 0x00, 0x00, 0x00}, 1000, 1000 + (5 + 1) * 5 * 60},
376 {{0x01, 150, 0x00, 0x00, 0x00}, 1000, 1000 + (12*60 + (150-143) * 30) * 60},
377 {{0x01, 180, 0x00, 0x00, 0x00}, 1000, 1000 + ((180 - 166) * 60 * 24) * 60},
378 {{0x01, 250, 0x00, 0x00, 0x00}, 1000, 1000 + ((250 - 192) * 60 * 24 * 7) * 60},
379 {{0x81, 0x00, 5, 0x00, 0x00}, 1000, 1000 + (5 + 1) * 5 * 60},
380 {{0x02, 123, 0x00, 0x00, 0x00}, 1000, 1000 + 123},
381 {{0x03, 0x20, 0x51, 0x32, 0x00}, 1000, 1000 + (2*60 + 15) * 60 + 23},
382 {{0x04, 0x00, 0x00, 0x00, 0x00}, 1000, 1000 + SMS_DEFAULT_VALIDITY_PERIOD},
383 };
384
385 printf("\nTesting default validity time\n");
386 valid_until = gsm340_validity_time(0, GSM340_TP_VPF_NONE, NULL);
387 PRINT_VALIDITY_TIMES(vp_rel_default, valid_until);
388 OSMO_ASSERT(valid_until == SMS_DEFAULT_VALIDITY_PERIOD);
389
390 printf("\nTesting relative validity time\n");
391 TEST_VALIDITY_DECODING(vp_rel_test, GSM340_TP_VPF_RELATIVE);
392
393 printf("\nTesting absolute validity time\n");
394 TEST_VALIDITY_DECODING(vp_abs_test, GSM340_TP_VPF_ABSOLUTE);
395
396 printf("\nTesting enhanced validity time\n");
397 TEST_VALIDITY_DECODING(vp_enh_test, GSM340_TP_VPF_ENHANCED);
398}
399
Harald Welteec8b4502010-02-20 20:34:29 +0100400int main(int argc, char** argv)
401{
402 printf("SMS testing\n");
Harald Welteec8b4502010-02-20 20:34:29 +0100403 uint8_t i;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200404 uint16_t buffer_size;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200405 uint8_t octet_length;
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200406 int octets_written;
407 uint8_t computed_octet_length;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200408 uint8_t septet_length;
Harald Welteec8b4502010-02-20 20:34:29 +0100409 uint8_t coded[256];
Dennis Wehrle291e6132011-07-24 20:14:13 +0200410 uint8_t tmp[160];
411 uint8_t septet_data[256];
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200412 int nchars;
Harald Welteec8b4502010-02-20 20:34:29 +0100413 char result[256];
414
Alexander Chemerisf6248612014-03-07 20:42:03 +0100415 /* Fake logging. */
416 osmo_init_logging(&fake_log_info);
417
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800418 /* test 7-bit encoding */
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200419 for (i = 0; i < ARRAY_SIZE(test_encode); ++i) {
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100420 /* Test legacy function (return value only) */
421 septet_length = gsm_7bit_encode(coded,
422 (const char *) test_encode[i].input);
423 printf("Legacy encode case %d: "
424 "septet length %d (expected %d)\n"
425 , i
426 , septet_length, test_encode[i].expected_septet_length
427 );
428 OSMO_ASSERT (septet_length == test_encode[i].expected_septet_length);
429
430 /* Test new function */
Nico Goldec0ce9aa2010-07-20 15:43:58 +0200431 memset(coded, 0x42, sizeof(coded));
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200432 septet_length = gsm_7bit_encode_n(coded, sizeof(coded),
433 (const char *) test_encode[i].input,
434 &octets_written);
435 computed_octet_length = gsm_get_octet_len(septet_length);
436 printf("Encode case %d: "
437 "Octet length %d (expected %d, computed %d), "
438 "septet length %d (expected %d)\n"
439 , i
440 , octets_written, test_encode[i].expected_octet_length, computed_octet_length
441 , septet_length, test_encode[i].expected_septet_length
442 );
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800443
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200444 OSMO_ASSERT (octets_written == test_encode[i].expected_octet_length);
445 OSMO_ASSERT (octets_written == computed_octet_length);
446 OSMO_ASSERT (memcmp(coded, test_encode[i].expected, octets_written) == 0);
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100447 OSMO_ASSERT (septet_length == test_encode[i].expected_septet_length);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200448
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200449 /* check buffer limiting */
450 memset(coded, 0xaa, sizeof(coded));
451
452 for (buffer_size = 0;
453 buffer_size < test_encode[i].expected_octet_length + 1
454 && buffer_size < sizeof(coded) - 1;
455 ++buffer_size)
456 {
457 gsm_7bit_encode_n(coded, buffer_size,
458 (const char *) test_encode[i].input,
459 &octets_written);
460
461 OSMO_ASSERT(octets_written <= buffer_size);
462 OSMO_ASSERT(coded[buffer_size] == 0xaa);
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800463 }
Harald Welteec8b4502010-02-20 20:34:29 +0100464 }
Nico Golde28de0532010-07-09 17:19:12 +0200465
Dennis Wehrle291e6132011-07-24 20:14:13 +0200466
467 /* Test: encode multiple SMS */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200468 int number_of_septets = gsm_septet_encode(septet_data, (const char *) test_multiple_encode[0].input);
Jacob Erlbeck73ae7a92013-10-08 12:04:42 +0200469 (void) number_of_septets;
Dennis Wehrle291e6132011-07-24 20:14:13 +0200470
471 /* SMS part 1 */
472 memset(tmp, 0x42, sizeof(tmp));
473 memset(coded, 0x42, sizeof(coded));
474 memcpy(tmp, septet_data, concatenated_part1_septet_length);
475
476 /* In our case: test_multiple_decode[0].ud_hdr_ind equals number of padding bits*/
477 octet_length = gsm_septets2octets(coded, tmp, concatenated_part1_septet_length, test_multiple_encode[0].ud_hdr_ind);
478
479 /* copy header */
480 memset(tmp, 0x42, sizeof(tmp));
481 int udh_length = test_multiple_encode[0].expected[0] + 1;
482 memcpy(tmp, test_multiple_encode[0].expected, udh_length);
483 memcpy(tmp + udh_length, coded, octet_length);
484 memset(coded, 0x42, sizeof(coded));
485 memcpy(coded, tmp, octet_length + 6);
486
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200487 OSMO_ASSERT(memcmp(coded, test_multiple_encode[0].expected, octet_length) == 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200488
489 /* SMS part 2 */
490 memset(tmp, 0x42, sizeof(tmp));
491 memset(coded, 0x42, sizeof(coded));
492 memcpy(tmp, septet_data + concatenated_part1_septet_length, concatenated_part2_septet_length);
493
494 /* In our case: test_multiple_decode[1].ud_hdr_ind equals number of padding bits*/
495 octet_length = gsm_septets2octets(coded, tmp, concatenated_part2_septet_length, test_multiple_encode[1].ud_hdr_ind);
496
497 /* copy header */
498 memset(tmp, 0x42, sizeof(tmp));
499 udh_length = test_multiple_encode[1].expected[0] + 1;
500 memcpy(tmp, test_multiple_encode[1].expected, udh_length);
501 memcpy(tmp + udh_length, coded, octet_length);
502 memset(coded, 0x42, sizeof(coded));
503 memcpy(coded, tmp, octet_length + 6);
504
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200505 OSMO_ASSERT(memcmp(coded, test_multiple_encode[1].expected, octet_length) == 0);
Dennis Wehrle291e6132011-07-24 20:14:13 +0200506
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800507 /* test 7-bit decoding */
508 for (i = 0; i < ARRAY_SIZE(test_decode); ++i) {
Jacob Erlbeck26cbd452014-01-07 13:39:24 +0100509 /* Test legacy function (return value only) */
510 if (!test_decode[i].ud_hdr_ind) {
511 nchars = gsm_7bit_decode(result, test_decode[i].input,
512 test_decode[i].expected_septet_length);
513 printf("Legacy decode case %d: "
514 "return value %d (expected %d)\n",
515 i, nchars, test_decode[i].expected_septet_length);
516 }
517
518 /* Test new function */
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200519 memset(result, 0x42, sizeof(result));
520 nchars = gsm_7bit_decode_n_hdr(result, sizeof(result), test_decode[i].input,
Dennis Wehrle291e6132011-07-24 20:14:13 +0200521 test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200522 printf("Decode case %d: return value %d (expected %d)\n", i, nchars, strlen(result));
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800523
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200524 OSMO_ASSERT(strcmp(result, (const char *) test_decode[i].expected) == 0);
525 OSMO_ASSERT(nchars == strlen(result));
526
527 /* check buffer limiting */
528 memset(result, 0xaa, sizeof(result));
529
530 for (buffer_size = 1;
Holger Hans Peter Freytherbb9f8972013-10-08 13:57:51 +0200531 buffer_size < test_decode[i].expected_septet_length + 1
Jacob Erlbeck1d7f3b52013-08-12 17:07:53 +0200532 && buffer_size < sizeof(result) - 1;
533 ++buffer_size)
534 {
535 nchars = gsm_7bit_decode_n_hdr(result, buffer_size, test_decode[i].input,
536 test_decode[i].expected_septet_length, test_decode[i].ud_hdr_ind);
537
538 OSMO_ASSERT(nchars <= buffer_size);
539 OSMO_ASSERT(result[buffer_size] == (char)0xaa);
540 OSMO_ASSERT(result[nchars] == '\0');
Dennis Wehrle291e6132011-07-24 20:14:13 +0200541 }
Nico Golde28de0532010-07-09 17:19:12 +0200542 }
543
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200544 test_octet_return();
Holger Hans Peter Freyther4d7e49b2013-05-02 22:37:16 +0200545 test_gen_oa();
Alexander Chemeris93d9a192014-03-07 20:55:21 +0100546 test_validity_period();
Holger Hans Peter Freyther6bfa7442013-08-08 12:38:52 +0200547
Holger Hans Peter Freyther31e97ea2010-07-20 02:46:56 +0800548 printf("OK\n");
Nico Golde28de0532010-07-09 17:19:12 +0200549 return 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100550}