libosmo-sccp/tests/ss7/ss7_test.c

331 lines
9.6 KiB
C

#include "../src/xua_internal.h"
#include "../src/xua_asp_fsm.h"
#include <osmocom/sigtran/osmo_ss7.h>
#include <osmocom/sigtran/protocol/m3ua.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
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.name = "testuser";
user.priv = (void *) 0x1234;
user.prim_cb = test_user_prim_cb;
/* 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(osmo_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(osmo_ss7_mtp_to_user(s7i, &omp) == -ENODEV);
/* wrong primitive delivery should also fail */
omp.oph.primitive = OSMO_MTP_PRIM_PAUSE;
OSMO_ASSERT(osmo_ss7_mtp_to_user(s7i, &omp) == -EINVAL);
}
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(osmo_ss7_route_table_find(s7i, "foobar") == NULL);
rtbl = osmo_ss7_route_table_find_or_create(s7i, "foobar");
OSMO_ASSERT(rtbl);
OSMO_ASSERT(osmo_ss7_route_table_find_or_create(s7i, "foobar") == rtbl);
osmo_ss7_route_table_destroy(rtbl);
OSMO_ASSERT(osmo_ss7_route_table_find(s7i, "foobar") == NULL);
/* we now work with system route table */
rtbl = osmo_ss7_route_table_find(s7i, "system");
OSMO_ASSERT(rtbl && rtbl == s7i->rtable_system);
lset_a = osmo_ss7_linkset_find_or_create(s7i, "a", 100);
OSMO_ASSERT(lset_a);
lset_b = osmo_ss7_linkset_find_or_create(s7i, "b", 200);
OSMO_ASSERT(lset_b);
/* route with full mask */
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 12) == NULL);
rt = osmo_ss7_route_create(rtbl, 12, 0xffff, "a");
printf("route with full mask: %s\n", osmo_ss7_route_print(rt));
OSMO_ASSERT(rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 12) == rt);
osmo_ss7_route_destroy(rt);
/* route with partial mask */
rt = osmo_ss7_route_create(rtbl, 8, 0xfff8, "a");
printf("route with partial mask: %s\n", osmo_ss7_route_print(rt));
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 8) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 9) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 12) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 15) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 16) == NULL);
/* insert more specific route for 12, must have higher priority
* than existing one */
rt12 = osmo_ss7_route_create(rtbl, 12, 0xffff, "b");
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 12) == rt12);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 15) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 16) == NULL);
/* add a default route, which should have lowest precedence */
rtdef = osmo_ss7_route_create(rtbl, 0, 0, "a");
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 12) == rt12);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 15) == rt);
OSMO_ASSERT(osmo_ss7_route_find_dpc(rtbl, 16) == rtdef);
osmo_ss7_route_destroy(rtdef);
osmo_ss7_route_destroy(rt12);
osmo_ss7_route_destroy(rt);
rt = osmo_ss7_route_create(rtbl, 8, 0xfff9, "a");
printf("route with non-consecutive mask: %s\n", osmo_ss7_route_print(rt));
osmo_ss7_route_destroy(rt);
osmo_ss7_linkset_destroy(lset_a);
osmo_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(osmo_ss7_linkset_find_by_name(s7i, "a") == NULL);
OSMO_ASSERT(osmo_ss7_linkset_find_by_name(s7i, "b") == NULL);
lset_a = osmo_ss7_linkset_find_or_create(s7i, "a", 100);
OSMO_ASSERT(lset_a);
OSMO_ASSERT(osmo_ss7_linkset_find_by_name(s7i, "a") == lset_a);
lset_b = osmo_ss7_linkset_find_or_create(s7i, "b", 200);
OSMO_ASSERT(lset_b);
OSMO_ASSERT(osmo_ss7_linkset_find_by_name(s7i, "b") == lset_b);
l_a1 = osmo_ss7_link_find_or_create(lset_a, 1);
OSMO_ASSERT(l_a1);
l_a2 = osmo_ss7_link_find_or_create(lset_a, 2);
OSMO_ASSERT(l_a2);
/* ID too high */
OSMO_ASSERT(osmo_ss7_link_find_or_create(lset_a, 1000) == NULL);
/* already exists */
OSMO_ASSERT(osmo_ss7_link_find_or_create(lset_a, 1) == l_a1);
osmo_ss7_link_destroy(l_a1);
osmo_ss7_link_destroy(l_a2);
osmo_ss7_linkset_destroy(lset_a);
osmo_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);
}