| /* |
| * (C) 2012 by Holger Hans Peter Freyther |
| * All Rights Reserved |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| */ |
| |
| #include <osmocom/gsm/gsm0808.h> |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #define VERIFY(msg, data, len) \ |
| if (msgb_l3len(msg) != len) { \ |
| printf("%s:%d Length don't match: %d vs. %d. %s\n", \ |
| __func__, __LINE__, msgb_l3len(msg), (int) len, \ |
| osmo_hexdump(msg->l3h, msgb_l3len(msg))); \ |
| abort(); \ |
| } else if (memcmp(msg->l3h, data, len) != 0) { \ |
| printf("%s:%d didn't match: got: %s\n", \ |
| __func__, __LINE__, \ |
| osmo_hexdump(msg->l3h, msgb_l3len(msg))); \ |
| abort(); \ |
| } |
| |
| |
| static void test_create_layer3(void) |
| { |
| static const uint8_t res[] = { |
| 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62, |
| 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 }; |
| struct msgb *msg, *in_msg; |
| printf("Testing creating Layer3\n"); |
| |
| in_msg = msgb_alloc_headroom(512, 128, "foo"); |
| in_msg->l3h = in_msg->data; |
| msgb_v_put(in_msg, 0x23); |
| |
| msg = gsm0808_create_layer3(in_msg, 0x1122, 0x2244, 0x3366, 0x4488); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| msgb_free(in_msg); |
| } |
| |
| static void test_create_reset() |
| { |
| static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 }; |
| struct msgb *msg; |
| |
| printf("Testing creating Reset\n"); |
| msg = gsm0808_create_reset(); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_clear_command() |
| { |
| static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 }; |
| struct msgb *msg; |
| |
| printf("Testing creating Clear Command\n"); |
| msg = gsm0808_create_clear_command(0x23); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_clear_complete() |
| { |
| static const uint8_t res[] = { 0x00, 0x01, 0x21 }; |
| struct msgb *msg; |
| |
| printf("Testing creating Clear Complete\n"); |
| msg = gsm0808_create_clear_complete(); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_cipher_complete() |
| { |
| static const uint8_t res1[] = { |
| 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 }; |
| static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04}; |
| struct msgb *l3, *msg; |
| |
| printf("Testing creating Cipher Complete\n"); |
| l3 = msgb_alloc_headroom(512, 128, "l3h"); |
| l3->l3h = l3->data; |
| msgb_v_put(l3, 0x23); |
| msgb_v_put(l3, 0x42); |
| msgb_v_put(l3, 0x21); |
| |
| /* with l3 data */ |
| msg = gsm0808_create_cipher_complete(l3, 4); |
| VERIFY(msg, res1, ARRAY_SIZE(res1)); |
| msgb_free(msg); |
| |
| /* with l3 data but short */ |
| l3->len -= 1; |
| l3->tail -= 1; |
| msg = gsm0808_create_cipher_complete(l3, 4); |
| VERIFY(msg, res2, ARRAY_SIZE(res2)); |
| msgb_free(msg); |
| |
| /* without l3 data */ |
| msg = gsm0808_create_cipher_complete(NULL, 4); |
| VERIFY(msg, res2, ARRAY_SIZE(res2)); |
| msgb_free(msg); |
| |
| |
| msgb_free(l3); |
| } |
| |
| static void test_create_cipher_reject() |
| { |
| static const uint8_t res[] = { 0x00, 0x02, 0x59, 0x23 }; |
| struct msgb *msg; |
| |
| printf("Testing creating Cipher Reject\n"); |
| msg = gsm0808_create_cipher_reject(0x23); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_cm_u() |
| { |
| static const uint8_t res[] = { |
| 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 }; |
| static const uint8_t res2o[] = { |
| 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 }; |
| struct msgb *msg; |
| const uint8_t cm2 = 0x23; |
| const uint8_t cm3 = 0x42; |
| |
| printf("Testing creating CM U\n"); |
| msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| |
| msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0); |
| VERIFY(msg, res2o, ARRAY_SIZE(res2o)); |
| |
| msgb_free(msg); |
| } |
| |
| static void test_create_sapi_reject() |
| { |
| static const uint8_t res[] = { 0x00, 0x03, 0x25, 0x03, 0x25 }; |
| struct msgb *msg; |
| |
| printf("Testing creating SAPI Reject\n"); |
| msg = gsm0808_create_sapi_reject(3); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_ass_compl() |
| { |
| static const uint8_t res1[] = { |
| 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, |
| 0x11, 0x40, 0x22 }; |
| static const uint8_t res2[] = { |
| 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11}; |
| struct msgb *msg; |
| |
| printf("Testing creating Assignment Complete\n"); |
| msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22); |
| VERIFY(msg, res1, ARRAY_SIZE(res1)); |
| msgb_free(msg); |
| |
| msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0); |
| VERIFY(msg, res2, ARRAY_SIZE(res2)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_ass_fail() |
| { |
| static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 }; |
| static const uint8_t res2[] = { |
| 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02}; |
| uint8_t rr_res = 2; |
| struct msgb *msg; |
| |
| printf("Testing creating Assignment Failure\n"); |
| msg = gsm0808_create_assignment_failure(0x23, NULL); |
| VERIFY(msg, res1, ARRAY_SIZE(res1)); |
| msgb_free(msg); |
| |
| msg = gsm0808_create_assignment_failure(0x23, &rr_res); |
| VERIFY(msg, res2, ARRAY_SIZE(res2)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_clear_rqst() |
| { |
| static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 }; |
| struct msgb *msg; |
| |
| printf("Testing creating Clear Request\n"); |
| msg = gsm0808_create_clear_rqst(0x23); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| } |
| |
| static void test_create_dtap() |
| { |
| static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 }; |
| struct msgb *msg, *l3; |
| |
| printf("Testing creating DTAP\n"); |
| l3 = msgb_alloc_headroom(512, 128, "test"); |
| l3->l3h = l3->data; |
| msgb_v_put(l3, 0x23); |
| msgb_v_put(l3, 0x42); |
| |
| msg = gsm0808_create_dtap(l3, 0x3); |
| VERIFY(msg, res, ARRAY_SIZE(res)); |
| msgb_free(msg); |
| msgb_free(l3); |
| } |
| |
| static void test_prepend_dtap() |
| { |
| static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 }; |
| struct msgb *in_msg; |
| |
| printf("Testing prepend DTAP\n"); |
| |
| in_msg = msgb_alloc_headroom(512, 128, "test"); |
| msgb_v_put(in_msg, 0x23); |
| msgb_v_put(in_msg, 0x42); |
| |
| gsm0808_prepend_dtap_header(in_msg, 0x3); |
| in_msg->l3h = in_msg->data; |
| VERIFY(in_msg, res, ARRAY_SIZE(res)); |
| msgb_free(in_msg); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| printf("Testing generation of GSM0808 messages\n"); |
| test_create_layer3(); |
| test_create_reset(); |
| test_create_clear_command(); |
| test_create_clear_complete(); |
| test_create_cipher_complete(); |
| test_create_cipher_reject(); |
| test_create_cm_u(); |
| test_create_sapi_reject(); |
| test_create_ass_compl(); |
| test_create_ass_fail(); |
| test_create_clear_rqst(); |
| test_create_dtap(); |
| test_prepend_dtap(); |
| |
| printf("Done\n"); |
| return EXIT_SUCCESS; |
| } |