blob: 26bd1d607aaf98dcad9f9855545f594c9bb5629a [file] [log] [blame]
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +01001/*
2 * (C) 2012 by Holger Hans Peter Freyther
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <osmocom/gsm/gsm0808.h>
Philipp Maier22401432017-03-24 17:59:26 +010022#include <osmocom/gsm/gsm0808_utils.h>
23#include <osmocom/gsm/protocol/gsm_08_08.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010024
25#include <stdio.h>
26#include <stdlib.h>
Philipp Maier22401432017-03-24 17:59:26 +010027#include <sys/socket.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010030
31#define VERIFY(msg, data, len) \
32 if (msgb_l3len(msg) != len) { \
33 printf("%s:%d Length don't match: %d vs. %d. %s\n", \
Holger Hans Peter Freytherfdb46672015-11-09 16:32:43 +000034 __func__, __LINE__, msgb_l3len(msg), (int) len, \
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +010035 osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
36 abort(); \
37 } else if (memcmp(msg->l3h, data, len) != 0) { \
38 printf("%s:%d didn't match: got: %s\n", \
39 __func__, __LINE__, \
40 osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
41 abort(); \
42 }
43
44
45static void test_create_layer3(void)
46{
47 static const uint8_t res[] = {
48 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
49 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
50 struct msgb *msg, *in_msg;
51 printf("Testing creating Layer3\n");
52
53 in_msg = msgb_alloc_headroom(512, 128, "foo");
54 in_msg->l3h = in_msg->data;
55 msgb_v_put(in_msg, 0x23);
56
57 msg = gsm0808_create_layer3(in_msg, 0x1122, 0x2244, 0x3366, 0x4488);
58 VERIFY(msg, res, ARRAY_SIZE(res));
59 msgb_free(msg);
60 msgb_free(in_msg);
61}
62
63static void test_create_reset()
64{
65 static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
66 struct msgb *msg;
67
68 printf("Testing creating Reset\n");
69 msg = gsm0808_create_reset();
70 VERIFY(msg, res, ARRAY_SIZE(res));
71 msgb_free(msg);
72}
73
74static void test_create_clear_command()
75{
76 static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
77 struct msgb *msg;
78
79 printf("Testing creating Clear Command\n");
80 msg = gsm0808_create_clear_command(0x23);
81 VERIFY(msg, res, ARRAY_SIZE(res));
82 msgb_free(msg);
83}
84
85static void test_create_clear_complete()
86{
87 static const uint8_t res[] = { 0x00, 0x01, 0x21 };
88 struct msgb *msg;
89
90 printf("Testing creating Clear Complete\n");
91 msg = gsm0808_create_clear_complete();
92 VERIFY(msg, res, ARRAY_SIZE(res));
93 msgb_free(msg);
94}
95
96static void test_create_cipher_complete()
97{
98 static const uint8_t res1[] = {
99 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
100 static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
101 struct msgb *l3, *msg;
102
103 printf("Testing creating Cipher Complete\n");
104 l3 = msgb_alloc_headroom(512, 128, "l3h");
105 l3->l3h = l3->data;
106 msgb_v_put(l3, 0x23);
107 msgb_v_put(l3, 0x42);
108 msgb_v_put(l3, 0x21);
109
110 /* with l3 data */
111 msg = gsm0808_create_cipher_complete(l3, 4);
112 VERIFY(msg, res1, ARRAY_SIZE(res1));
113 msgb_free(msg);
114
115 /* with l3 data but short */
116 l3->len -= 1;
117 l3->tail -= 1;
118 msg = gsm0808_create_cipher_complete(l3, 4);
119 VERIFY(msg, res2, ARRAY_SIZE(res2));
120 msgb_free(msg);
121
122 /* without l3 data */
123 msg = gsm0808_create_cipher_complete(NULL, 4);
124 VERIFY(msg, res2, ARRAY_SIZE(res2));
125 msgb_free(msg);
126
127
128 msgb_free(l3);
129}
130
131static void test_create_cipher_reject()
132{
133 static const uint8_t res[] = { 0x00, 0x02, 0x59, 0x23 };
134 struct msgb *msg;
135
136 printf("Testing creating Cipher Reject\n");
137 msg = gsm0808_create_cipher_reject(0x23);
138 VERIFY(msg, res, ARRAY_SIZE(res));
139 msgb_free(msg);
140}
141
142static void test_create_cm_u()
143{
Harald Welte07b625d2012-01-23 10:02:58 +0100144 static const uint8_t res[] = {
145 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
146 static const uint8_t res2o[] = {
147 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100148 struct msgb *msg;
Harald Welte07b625d2012-01-23 10:02:58 +0100149 const uint8_t cm2 = 0x23;
150 const uint8_t cm3 = 0x42;
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100151
152 printf("Testing creating CM U\n");
Harald Welte07b625d2012-01-23 10:02:58 +0100153 msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100154 VERIFY(msg, res, ARRAY_SIZE(res));
Harald Welte07b625d2012-01-23 10:02:58 +0100155
156 msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
157 VERIFY(msg, res2o, ARRAY_SIZE(res2o));
158
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100159 msgb_free(msg);
160}
161
162static void test_create_sapi_reject()
163{
164 static const uint8_t res[] = { 0x00, 0x03, 0x25, 0x03, 0x25 };
165 struct msgb *msg;
166
167 printf("Testing creating SAPI Reject\n");
168 msg = gsm0808_create_sapi_reject(3);
169 VERIFY(msg, res, ARRAY_SIZE(res));
170 msgb_free(msg);
171}
172
173static void test_create_ass_compl()
174{
175 static const uint8_t res1[] = {
176 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
177 0x11, 0x40, 0x22 };
178 static const uint8_t res2[] = {
179 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
180 struct msgb *msg;
181
182 printf("Testing creating Assignment Complete\n");
183 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
184 VERIFY(msg, res1, ARRAY_SIZE(res1));
185 msgb_free(msg);
186
187 msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
188 VERIFY(msg, res2, ARRAY_SIZE(res2));
189 msgb_free(msg);
190}
191
192static void test_create_ass_fail()
193{
194 static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
195 static const uint8_t res2[] = {
196 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
197 uint8_t rr_res = 2;
198 struct msgb *msg;
199
200 printf("Testing creating Assignment Failure\n");
201 msg = gsm0808_create_assignment_failure(0x23, NULL);
202 VERIFY(msg, res1, ARRAY_SIZE(res1));
203 msgb_free(msg);
204
205 msg = gsm0808_create_assignment_failure(0x23, &rr_res);
206 VERIFY(msg, res2, ARRAY_SIZE(res2));
207 msgb_free(msg);
208}
209
210static void test_create_clear_rqst()
211{
212 static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
213 struct msgb *msg;
214
215 printf("Testing creating Clear Request\n");
216 msg = gsm0808_create_clear_rqst(0x23);
217 VERIFY(msg, res, ARRAY_SIZE(res));
218 msgb_free(msg);
219}
220
221static void test_create_dtap()
222{
223 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
224 struct msgb *msg, *l3;
225
226 printf("Testing creating DTAP\n");
227 l3 = msgb_alloc_headroom(512, 128, "test");
228 l3->l3h = l3->data;
229 msgb_v_put(l3, 0x23);
230 msgb_v_put(l3, 0x42);
231
232 msg = gsm0808_create_dtap(l3, 0x3);
233 VERIFY(msg, res, ARRAY_SIZE(res));
234 msgb_free(msg);
235 msgb_free(l3);
236}
237
238static void test_prepend_dtap()
239{
240 static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
241 struct msgb *in_msg;
242
243 printf("Testing prepend DTAP\n");
244
245 in_msg = msgb_alloc_headroom(512, 128, "test");
246 msgb_v_put(in_msg, 0x23);
247 msgb_v_put(in_msg, 0x42);
248
249 gsm0808_prepend_dtap_header(in_msg, 0x3);
250 in_msg->l3h = in_msg->data;
251 VERIFY(in_msg, res, ARRAY_SIZE(res));
252 msgb_free(in_msg);
253}
254
Philipp Maier22401432017-03-24 17:59:26 +0100255static void test_enc_dec_aoip_trasp_addr_v4()
256{
257 struct sockaddr_storage enc_addr;
258 struct sockaddr_storage dec_addr;
259 struct sockaddr_in enc_addr_in;
260 struct msgb *msg;
261 uint8_t rc_enc;
262 int rc_dec;
263
264 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
265 enc_addr_in.sin_family = AF_INET;
266 enc_addr_in.sin_port = htons(1234);
267 inet_aton("255.0.255.255", &enc_addr_in.sin_addr);
268
269 memset(&enc_addr, 0, sizeof(enc_addr));
270 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
271
272 msg = msgb_alloc(1024, "output buffer");
273 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
274 OSMO_ASSERT(rc_enc == 8);
275 rc_dec =
276 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
277 OSMO_ASSERT(rc_dec == 6);
278 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
279
280 msgb_free(msg);
281}
282
283static void test_enc_dec_aoip_trasp_addr_v6()
284{
285 struct sockaddr_storage enc_addr;
286 struct sockaddr_storage dec_addr;
287 struct sockaddr_in6 enc_addr_in;
288 struct msgb *msg;
289 uint8_t rc_enc;
290 int rc_dec;
291
292 memset(&enc_addr_in, 0, sizeof(enc_addr_in));
293 enc_addr_in.sin6_family = AF_INET6;
294 enc_addr_in.sin6_port = htons(4567);
295 inet_pton(AF_INET6, "2001:0db8:85a3:08d3:1319:8a2e:0370:7344",
296 &enc_addr_in.sin6_addr);
297
298 memset(&enc_addr, 0, sizeof(enc_addr));
299 memcpy(&enc_addr, &enc_addr_in, sizeof(enc_addr_in));
300
301 msg = msgb_alloc(1024, "output buffer");
302 rc_enc = gsm0808_enc_aoip_trasp_addr(msg, &enc_addr);
303 OSMO_ASSERT(rc_enc == 20);
304 rc_dec =
305 gsm0808_dec_aoip_trasp_addr(&dec_addr, msg->data + 2, msg->len - 2);
306 OSMO_ASSERT(rc_dec == 18);
307 OSMO_ASSERT(memcmp(&enc_addr, &dec_addr, sizeof(enc_addr)) == 0);
308
309 msgb_free(msg);
310}
311
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100312int main(int argc, char **argv)
313{
314 printf("Testing generation of GSM0808 messages\n");
315 test_create_layer3();
316 test_create_reset();
317 test_create_clear_command();
318 test_create_clear_complete();
319 test_create_cipher_complete();
320 test_create_cipher_reject();
321 test_create_cm_u();
322 test_create_sapi_reject();
323 test_create_ass_compl();
324 test_create_ass_fail();
325 test_create_clear_rqst();
326 test_create_dtap();
327 test_prepend_dtap();
Philipp Maier22401432017-03-24 17:59:26 +0100328 test_enc_dec_aoip_trasp_addr_v4();
329 test_enc_dec_aoip_trasp_addr_v6();
Holger Hans Peter Freyther97510812012-01-22 13:36:52 +0100330
331 printf("Done\n");
332 return EXIT_SUCCESS;
333}