#include "../src/ss7_as.h" #include "../src/ss7_asp.h" #include "../src/ss7_link.h" #include "../src/ss7_linkset.h" #include "../src/ss7_route.h" #include "../src/ss7_route_table.h" #include "../src/ss7_user.h" #include "../src/xua_internal.h" #include "../src/xua_asp_fsm.h" #include #include #include #include #include #include #include #include #include #include #include static struct osmo_ss7_instance *s7i; static void test_pc_transcode(uint32_t pc) { const char *pc_str = osmo_ss7_pointcode_print(s7i, pc); uint32_t pc_reenc = osmo_ss7_pointcode_parse(s7i, pc_str); printf("%s(%u) -> %s -> %u\n", __func__, pc, pc_str, pc_reenc); OSMO_ASSERT(pc == pc_reenc); } static void test_pc_defaults(void) { /* ensure the default point code format settings apply */ OSMO_ASSERT(s7i->cfg.pc_fmt.component_len[0] == 3); OSMO_ASSERT(s7i->cfg.pc_fmt.component_len[1] == 8); OSMO_ASSERT(s7i->cfg.pc_fmt.component_len[2] == 3); OSMO_ASSERT(s7i->cfg.pc_fmt.delimiter == '.'); } static void parse_print_mask(const char *in) { uint32_t mask = osmo_ss7_pointcode_parse_mask_or_len(s7i, in); const char *pc_str = osmo_ss7_pointcode_print(s7i, mask); printf("mask %s => %u (0x%x) %s\n", in, mask, mask, pc_str); } static void test_pc_parser_itu(void) { /* ITU Style */ printf("Testing ITU-style point code format\n"); osmo_ss7_instance_set_pc_fmt(s7i, 3, 8, 3); test_pc_transcode(0); test_pc_transcode(1); test_pc_transcode(1 << 3); test_pc_transcode(1 << (3+8)); test_pc_transcode(7 << (3+8)); test_pc_transcode(100); test_pc_transcode(2342); test_pc_transcode((1 << 14)-1); parse_print_mask("/1"); parse_print_mask("7.0.0"); parse_print_mask("/14"); } static void test_pc_parser_ansi(void) { /* ANSI Style */ printf("Testing ANSI-style point code format\n"); osmo_ss7_instance_set_pc_fmt(s7i, 8, 8, 8); s7i->cfg.pc_fmt.delimiter = '-'; test_pc_transcode(0); test_pc_transcode(1); test_pc_transcode(1 << 8); test_pc_transcode(1 << 16); test_pc_transcode(1 << (3+8)); test_pc_transcode((1 << 24)-1); test_pc_transcode(100); test_pc_transcode(2342); parse_print_mask("/1"); parse_print_mask("/16"); parse_print_mask("/24"); /* re-set to default (ITU) */ osmo_ss7_instance_set_pc_fmt(s7i, 3, 8, 3); s7i->cfg.pc_fmt.delimiter = '.'; } static int test_user_prim_cb(struct osmo_prim_hdr *oph, void *priv) { OSMO_ASSERT(priv == (void *) 0x1234); return 23; } static void test_user(void) { struct osmo_ss7_user *user, *user2; struct osmo_mtp_prim omp = { .oph = { .sap = MTP_SAP_USER, .primitive = OSMO_MTP_PRIM_TRANSFER, .operation = PRIM_OP_INDICATION, }, .u.transfer = { .sio = 1, }, }; printf("Testing SS7 user\n"); user = osmo_ss7_user_create(s7i, "testuser"); osmo_ss7_user_set_prim_cb(user, test_user_prim_cb); osmo_ss7_user_set_priv(user, (void *) 0x1234); user2 = osmo_ss7_user_create(s7i, "testuser_notregistered"); osmo_ss7_user_set_prim_cb(user, test_user_prim_cb); osmo_ss7_user_set_priv(user, (void *) 0x1234); /* registration */ OSMO_ASSERT(osmo_ss7_user_register(s7i, 1, user) == 0); OSMO_ASSERT(osmo_ss7_user_register(s7i, 1, NULL) == -EBUSY); OSMO_ASSERT(osmo_ss7_user_register(s7i, 255, NULL) == -EINVAL); /* primitive delivery */ OSMO_ASSERT(ss7_mtp_to_user(s7i, &omp) == 23); /* cleanup */ OSMO_ASSERT(osmo_ss7_user_unregister(s7i, 255, NULL) == -EINVAL); OSMO_ASSERT(osmo_ss7_user_unregister(s7i, 10, NULL) == -ENODEV); OSMO_ASSERT(osmo_ss7_user_unregister(s7i, 1, user2) == -EINVAL); OSMO_ASSERT(osmo_ss7_user_unregister(s7i, 1, user) == 0); /* primitive delivery should fail now */ OSMO_ASSERT(ss7_mtp_to_user(s7i, &omp) == -ENODEV); /* wrong primitive delivery should also fail */ omp.oph.primitive = OSMO_MTP_PRIM_PAUSE; OSMO_ASSERT(ss7_mtp_to_user(s7i, &omp) == -EINVAL); osmo_ss7_user_destroy(user); osmo_ss7_user_destroy(user2); } static void test_route(void) { struct osmo_ss7_route_table *rtbl; struct osmo_ss7_linkset *lset_a, *lset_b; struct osmo_ss7_route *rt, *rt12, *rtdef; printf("Testing SS7 routing\n"); /* creation / destruction */ OSMO_ASSERT(ss7_route_table_find(s7i, "foobar") == NULL); rtbl = ss7_route_table_find_or_create(s7i, "foobar"); OSMO_ASSERT(rtbl); OSMO_ASSERT(ss7_route_table_find_or_create(s7i, "foobar") == rtbl); ss7_route_table_destroy(rtbl); OSMO_ASSERT(ss7_route_table_find(s7i, "foobar") == NULL); /* we now work with system route table */ rtbl = ss7_route_table_find(s7i, "system"); OSMO_ASSERT(rtbl && rtbl == s7i->rtable_system); lset_a = ss7_linkset_find_or_create(s7i, "a", 100); OSMO_ASSERT(lset_a); lset_b = ss7_linkset_find_or_create(s7i, "b", 200); OSMO_ASSERT(lset_b); /* route with full mask */ OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == NULL); rt = ss7_route_create(rtbl, 12, 0xffff, "a"); printf("route with full mask: %s\n", osmo_ss7_route_print(rt)); OSMO_ASSERT(rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt); ss7_route_destroy(rt); /* route with partial mask */ rt = ss7_route_create(rtbl, 8, 0xfff8, "a"); printf("route with partial mask: %s\n", osmo_ss7_route_print(rt)); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 8) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 9) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL); /* insert more specific route for 12, must have higher priority * than existing one */ rt12 = ss7_route_create(rtbl, 12, 0xffff, "b"); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL); /* add a default route, which should have lowest precedence */ rtdef = ss7_route_create(rtbl, 0, 0, "a"); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == rtdef); ss7_route_destroy(rtdef); ss7_route_destroy(rt12); ss7_route_destroy(rt); rt = ss7_route_create(rtbl, 8, 0xfff9, "a"); printf("route with non-consecutive mask: %s\n", osmo_ss7_route_print(rt)); ss7_route_destroy(rt); ss7_linkset_destroy(lset_a); ss7_linkset_destroy(lset_b); } static void test_linkset(void) { struct osmo_ss7_linkset *lset_a, *lset_b; struct osmo_ss7_link *l_a1, *l_a2; printf("Testing SS7 linkset/link\n"); OSMO_ASSERT(ss7_linkset_find_by_name(s7i, "a") == NULL); OSMO_ASSERT(ss7_linkset_find_by_name(s7i, "b") == NULL); lset_a = ss7_linkset_find_or_create(s7i, "a", 100); OSMO_ASSERT(lset_a); OSMO_ASSERT(ss7_linkset_find_by_name(s7i, "a") == lset_a); lset_b = ss7_linkset_find_or_create(s7i, "b", 200); OSMO_ASSERT(lset_b); OSMO_ASSERT(ss7_linkset_find_by_name(s7i, "b") == lset_b); l_a1 = ss7_link_find_or_create(lset_a, 1); OSMO_ASSERT(l_a1); l_a2 = ss7_link_find_or_create(lset_a, 2); OSMO_ASSERT(l_a2); /* ID too high */ OSMO_ASSERT(ss7_link_find_or_create(lset_a, 1000) == NULL); /* already exists */ OSMO_ASSERT(ss7_link_find_or_create(lset_a, 1) == l_a1); ss7_link_destroy(l_a1); ss7_link_destroy(l_a2); ss7_linkset_destroy(lset_a); ss7_linkset_destroy(lset_b); } static void test_as(void) { struct osmo_ss7_as *as; struct osmo_ss7_asp *asp; OSMO_ASSERT(osmo_ss7_as_find_by_name(s7i, "as1") == NULL); as = osmo_ss7_as_find_or_create(s7i, "as1", OSMO_SS7_ASP_PROT_M3UA); OSMO_ASSERT(as); OSMO_ASSERT(osmo_ss7_as_find_by_name(s7i, "as1") == as); OSMO_ASSERT(osmo_ss7_as_find_by_rctx(s7i, 2342) == NULL); as->cfg.routing_key.context = 2342; OSMO_ASSERT(osmo_ss7_as_find_by_rctx(s7i, 2342) == as); OSMO_ASSERT(osmo_ss7_as_add_asp(as, "asp1") == -ENODEV); asp = osmo_ss7_asp_find_or_create2(s7i, "asp1", 0, M3UA_PORT, IPPROTO_SCTP, OSMO_SS7_ASP_PROT_M3UA); OSMO_ASSERT(asp); OSMO_ASSERT(osmo_ss7_as_has_asp(as, asp) == false); OSMO_ASSERT(osmo_ss7_as_add_asp(as, "asp1") == 0); osmo_ss7_asp_restart(asp); /* ask FSM to send ASP-UP.req */ osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_M_ASP_UP_REQ, NULL); osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_ASPSM_ASPUP_ACK, NULL); osmo_fsm_inst_dispatch(asp->fi, XUA_ASP_E_ASPTM_ASPAC_ACK, NULL); OSMO_ASSERT(osmo_ss7_as_del_asp(as, "asp1") == 0); OSMO_ASSERT(osmo_ss7_as_del_asp(as, "asp2") == -ENODEV); OSMO_ASSERT(osmo_ss7_as_del_asp(as, "asp1") == -EINVAL); osmo_ss7_asp_destroy(asp); osmo_ss7_as_destroy(as); OSMO_ASSERT(osmo_ss7_as_find_by_name(s7i, "as1") == NULL); } /*********************************************************************** * Initialization ***********************************************************************/ static const struct log_info_cat log_info_cat[] = { }; static const struct log_info log_info = { .cat = log_info_cat, .num_cat = ARRAY_SIZE(log_info_cat), }; static void init_logging(void) { const int log_cats[] = { DLSS7, DLSUA, DLM3UA, DLSCCP, DLINP }; unsigned int i; void *tall_ctx = talloc_named_const(NULL, 1, "example"); msgb_talloc_ctx_init(tall_ctx, 0); osmo_init_logging2(tall_ctx, &log_info); log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); for (i = 0; i < ARRAY_SIZE(log_cats); i++) log_set_category_filter(osmo_stderr_target, log_cats[i], 1, LOGL_DEBUG); } int main(int argc, char **argv) { init_logging(); osmo_fsm_log_addr(false); /* init */ OSMO_ASSERT(osmo_ss7_init() == 0); s7i = osmo_ss7_instance_find_or_create(NULL, 0); OSMO_ASSERT(osmo_ss7_instance_find(0) == s7i); OSMO_ASSERT(osmo_ss7_instance_find(23) == NULL); /* test osmo_ss7_pc_is_local() */ s7i->cfg.primary_pc = 55; OSMO_ASSERT(osmo_ss7_pc_is_local(s7i, 55) == true); OSMO_ASSERT(osmo_ss7_pc_is_local(s7i, 23) == false); /* further tests */ test_pc_defaults(); test_pc_parser_itu(); test_pc_parser_ansi(); test_user(); test_route(); test_linkset(); test_as(); /* destroy */ osmo_ss7_instance_destroy(s7i); OSMO_ASSERT(osmo_ss7_instance_find(0) == NULL); exit(0); }