blob: ac470fc7345f880dac9161e71581fa14c9e67456 [file] [log] [blame]
Maxf74cfd32017-03-24 20:16:33 +01001/*
2 * (C) 2012 by Holger Hans Peter Freyther <zecke@selfish.org>
Vadim Yanitskiy03590fc2023-05-18 17:22:26 +07003 * (C) 2017 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Maxf74cfd32017-03-24 20:16:33 +01004 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
Maxf74cfd32017-03-24 20:16:33 +010016 */
17
18#include <osmocom/core/application.h>
19#include <osmocom/core/logging.h>
20#include <osmocom/core/utils.h>
21#include <osmocom/gsm/lapdm.h>
22#include <osmocom/gsm/rsl.h>
23#include <osmocom/gsm/protocol/gsm_12_21.h>
24
25#include <errno.h>
26#include <stdbool.h>
27#include <string.h>
28
29static struct log_info info = {};
30
31static const uint8_t simple_config[] = { 66, 18, 0, 3, 1, 2, 3, 19, 0, 3, 3, 4, 5 };
32
33static const uint8_t dual_config[] = {
34 66, 18, 0, 3, 1, 2, 3, 19, 0, 3, 3, 4, 5,
35 66, 18, 0, 3, 9, 7, 5, 19, 0, 3, 6, 7, 8,
36};
37
38static void test_simple_sw_config(void)
39{
40 struct abis_nm_sw_desc desc[1];
41 uint16_t len;
42 int rc;
43
44 rc = abis_nm_get_sw_conf(simple_config, ARRAY_SIZE(simple_config), &desc[0], ARRAY_SIZE(desc));
45 if (rc != 1) {
46 printf("%s(): FAILED to parse the File Id/File version: %d\n", __func__, rc);
47 abort();
48 }
49
50 len = abis_nm_sw_desc_len(&desc[0], true);
51 if (len != 13) {
52 printf("WRONG SIZE: %u\n", len);
53 abort();
54 }
55
56 printf("len: %u\n", len);
57 printf("file_id: %s\n", osmo_hexdump(desc[0].file_id, desc[0].file_id_len));
58 printf("file_ver: %s\n", osmo_hexdump(desc[0].file_version, desc[0].file_version_len));
59 printf("%s(): OK\n", __func__);
60}
61
62static void test_simple_sw_short(void)
63{
64 struct abis_nm_sw_desc desc[1];
65 int i;
66
67 for (i = 1; i < ARRAY_SIZE(simple_config); ++i) {
68 int rc = abis_nm_get_sw_conf(simple_config, ARRAY_SIZE(simple_config) - i, &desc[0], ARRAY_SIZE(desc));
69 if (rc >= 1) {
70 printf("SHOULD not have parsed: %d\n", rc);
71 abort();
72 }
73 }
74 printf("%s(): OK\n", __func__);
75}
76
77static void test_dual_sw_config(void)
78{
79 struct abis_nm_sw_desc desc[2];
80 uint16_t len0, len1;
81 int rc;
82
83 rc = abis_nm_get_sw_conf(dual_config, ARRAY_SIZE(dual_config), &desc[0], ARRAY_SIZE(desc));
84 if (rc != 2) {
85 printf("%s(): FAILED to parse the File Id/File version: %d (%d,%d)\n",
86 __func__, -rc, EBADF, EBADMSG);
87 abort();
88 }
89
90 len0 = abis_nm_sw_desc_len(&desc[0], true);
91 if (len0 != 13) {
92 printf("WRONG SIZE0: %u\n", len0);
93 abort();
94 }
95
96 len1 = abis_nm_sw_desc_len(&desc[1], true);
97 if (len1 != 13) {
98 printf("WRONG SIZE1: %u\n", len1);
99 abort();
100 }
101
102 printf("len: %u\n", len0);
103 printf("file_id: %s\n", osmo_hexdump(desc[0].file_id, desc[0].file_id_len));
104 printf("file_ver: %s\n", osmo_hexdump(desc[0].file_version, desc[0].file_version_len));
105
106 printf("len: %u\n", len1);
107 printf("file_id: %s\n", osmo_hexdump(desc[1].file_id, desc[1].file_id_len));
108 printf("file_ver: %s\n", osmo_hexdump(desc[1].file_version, desc[1].file_version_len));
109 printf("%s(): OK\n", __func__);
110}
111
112static inline void print_chk(const char *what, uint8_t len1, uint8_t len2, const uint8_t *x1, const uint8_t *x2)
113{
114 int cmp = memcmp(x1, x2, len2);
115 printf("\tFILE %s [%u == %u -> %d, %s] %d => %s\n", what, len1, len2, len1 == len2, len1 != len2 ? "fail" : "ok",
116 cmp, cmp != 0 ? "FAIL" : "OK");
117}
118
119static inline void chk_raw(const char *what, const uint8_t *data, uint16_t len)
120{
Pau Espin Pedrol039171a2017-06-18 11:21:25 +0200121 /* = { 0 } triggers a warning in some gcc versions due to a bug: gcc issue #53119 */
122 struct abis_nm_sw_desc sw = { {0} };
Maxf74cfd32017-03-24 20:16:33 +0100123 int res = abis_nm_get_sw_conf(data, len, &sw, 1);
124 uint16_t xlen = abis_nm_get_sw_desc_len(data, len);
125
126 printf("parsing chained %s <1st: %d, total: %d>\n\tSW Descr (%s)\n", osmo_hexdump(data, len), xlen, len, what);
127
128 if (res < 0)
129 printf("\tFAIL: %d\n", -res);
130 else {
131 printf("\tFILE ID: [%d] %s => OK\n", sw.file_id_len, osmo_hexdump(sw.file_id, sw.file_id_len));
132 printf("\tFILE VERSION: [%d] %s => OK\n", sw.file_version_len,
133 osmo_hexdump(sw.file_version, sw.file_version_len));
134 }
135
136 if (len != xlen)
137 chk_raw(" 2nd", data + xlen, len - xlen);
138}
139
140static inline void chk_descr(struct msgb *msg, const char *f_id, const char *f_ver, const char *desc, bool header)
141{
142 int res;
143 uint16_t len;
Pau Espin Pedrol039171a2017-06-18 11:21:25 +0200144 /* = { 0 } triggers a warning in some gcc versions due to a bug: gcc issue #53119 */
145 struct abis_nm_sw_desc sw = { {0} }, put = {
Maxf74cfd32017-03-24 20:16:33 +0100146 .file_id_len = strlen(f_id),
147 .file_version_len = strlen(f_ver),
148 };
149
150 memcpy(put.file_id, f_id, put.file_id_len);
151 memcpy(put.file_version, f_ver, put.file_version_len);
152 len = abis_nm_put_sw_file(msg, f_id, f_ver, header);
153
154 printf("msgb[%u] :: {msgb->len} %u == %u {len} - %s]:\n\tSW DESCR (%s)\n"
155 "\tlength: {extracted} %u = %u {expected} - %s, failsafe - %s\n",
156 msg->data_len, msg->len, len, len != msg->len ? "fail" : "ok", desc,
157 abis_nm_get_sw_desc_len(msgb_data(msg), msg->len), msg->len,
158 abis_nm_get_sw_desc_len(msgb_data(msg), msg->len) != msg->len ? "FAIL" : "OK",
159 len > put.file_version_len + put.file_id_len ? "OK" : "FAIL");
160
161 res = abis_nm_get_sw_conf(msgb_data(msg), msg->len, &sw, 1);
162 if (res < 0)
163 printf("\tSW DESCR (%s) parsing error code %d!\n", desc, -res);
164 else {
165 print_chk("ID", sw.file_id_len, put.file_id_len, sw.file_id, put.file_id);
166 print_chk("VERSION", sw.file_version_len, put.file_version_len, sw.file_version, put.file_version);
167 }
168}
169
Harald Weltee61d4592022-11-03 11:05:58 +0100170static void test_sw_descr(void)
Maxf74cfd32017-03-24 20:16:33 +0100171{
172 const char *f_id = "TEST.L0L", *f_ver = "0.1.666~deadbeeffacefeed-dirty";
173 uint8_t chain[] = { 0x42, 0x12, 0x00, 0x03, 0x01, 0x02, 0x03, 0x13, 0x00, 0x03, 0x03, 0x04, 0x05, 0x42, 0x12,
174 0x00, 0x03, 0x09, 0x07, 0x05, 0x13, 0x00, 0x03, 0x06, 0x07, 0x08 };
175 struct msgb *msg = msgb_alloc_headroom(4096, 128, "sw");
176
177 printf("Testing SW Description (de)serialization...\n");
178
179 /* check that parsing |SW|ID|VER| works: */
180 chk_descr(msg, f_id, f_ver, "with header", true);
181 msgb_reset(msg);
182
183 /* check that parsing |ID|VER| works: */
184 chk_descr(msg, f_id, f_ver, "without header", false);
185
186 /* check that parsing |ID|VER|SW|ID|VER| fails - notice the lack of msgb_reset() to create bogus msgb data: */
187 chk_descr(msg, f_id, f_ver, "expected failure", true);
188
189 /* check multiple, chained SW-descr: */
190 chk_raw("half", chain, sizeof(chain) / 2);
191 chk_raw("full", chain, sizeof(chain));
Neels Hofmeyr39720ac2017-11-16 16:24:36 +0100192
193 msgb_free(msg);
Maxf74cfd32017-03-24 20:16:33 +0100194}
195
Pau Espin Pedrol388a53a2022-04-04 19:26:05 +0200196/* Test decode IPAC_DLCX_IND obtained from SYS#5915 */
Harald Weltee61d4592022-11-03 11:05:58 +0100197static void test_dec_ipac_dlc_indx(void)
Pau Espin Pedrol388a53a2022-04-04 19:26:05 +0200198{
199/* Radio Signalling Link (RSL)
200 0111 111. = Message discriminator: ip.access Vendor Specific messages (63)
201 .... ...0 = T bit: Not considered transparent by BTS
202 .111 0110 = Message type: ip.access DLCX INDication (0x76)
203 Channel number IE
204 Element identifier: Channel Number (0x01)
205 0000 1... = C-bits: Bm + ACCH (1)
206 .... .110 = Time slot number (TN): 6
207 Element identifier: Connection Identifier (0xf8)
208 ip.access Connection ID: 0
209 Element identifier: Connection Statistics (0xf6)
210 [1 byte length here, val = 28 (0x1c)]
211 Packets Sent: 1202
212 Octets Sent: 45052
213 Packets Received: 556
214 Octets Received: 24580
215 Packets Lost: 0
216 Inter-arrival Jitter: 0
217 Average Tx Delay: 0
218 Cause IE
219 Element identifier: Cause (0x1a)
220 Length: 1
221 0... .... = Extension: No Extension
222 .000 .... = Class: Normal event (0)
223 .000 1111 = Cause Value: normal event, unspecified (15)
224*/
225 const uint8_t hex[] = {
226 0x7e, 0x76, 0x01, 0x0e, 0xf8, 0x00, 0x00, 0xf6, 0x1c, 0x00, 0x00, 0x04, 0xb2, 0x00, 0x00, 0xaf,
227 0xfc, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x01, 0x0f
229 };
230 struct abis_rsl_dchan_hdr *dh = (struct abis_rsl_dchan_hdr *)&hex[0];
231
232 struct tlv_parsed tp;
233 int rc;
234
235 printf("Testing decoding IPAC_DLCX_IND\n");
236
237 rc = rsl_tlv_parse(&tp, dh->data, sizeof(hex) - sizeof(*dh));
238
239 OSMO_ASSERT(rc == 3);
240}
241
Maxf74cfd32017-03-24 20:16:33 +0100242int main(int argc, char **argv)
243{
Neels Hofmeyra829b452018-04-05 03:02:35 +0200244 void *ctx = talloc_named_const(NULL, 0, "abis_test");
245 osmo_init_logging2(ctx, &info);
Maxf74cfd32017-03-24 20:16:33 +0100246
247 test_sw_descr();
248 test_simple_sw_config();
249 test_simple_sw_short();
250 test_dual_sw_config();
Pau Espin Pedrol388a53a2022-04-04 19:26:05 +0200251 test_dec_ipac_dlc_indx();
Maxf74cfd32017-03-24 20:16:33 +0100252
253 printf("OK.\n");
254
255 return 0;
256}