#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "internal.h" static const char *config_file; static struct osmo_sccp_instance *g_sccp; static struct osmo_sccp_instance *sua_server_helper(enum osmo_ss7_asp_protocol protocol, int local_port, const char *local_address, int local_pc, int remote_port, const char *remote_address, int remote_pc) { struct osmo_sccp_instance *sccp; sccp = osmo_sccp_simple_server(NULL, local_pc, protocol, local_port, local_address); if (sccp == NULL) return NULL; osmo_sccp_simple_server_add_clnt(sccp, protocol, "client", remote_pc, local_port, remote_port, remote_address); return sccp; } /*********************************************************************** * Initialization ***********************************************************************/ static void signal_handler(int signal) { fprintf(stdout, "signal %d received\n", signal); switch (signal) { case SIGUSR1: talloc_report_full(osmo_sccp_get_ss7(g_sccp), stderr); break; case SIGUSR2: talloc_report_full(NULL, stderr); break; } } static const struct log_info_cat log_info_cat[] = { [DMAIN] = { .name = "DMAIN", .description = "sccp_demo_user specific logging", .color = "\033[1;31m", .enabled = 1, .loglevel = LOGL_INFO, }, }; static const struct log_info log_info = { .cat = log_info_cat, .num_cat = ARRAY_SIZE(log_info_cat), }; static void init_logging(void *tall_ctx) { const int log_cats[] = { DLSS7, DLSUA, DLM3UA, DLSCCP, DLINP }; unsigned int i; msgb_talloc_ctx_init(tall_ctx, 0); osmo_init_logging2(tall_ctx, &log_info); log_set_print_category(osmo_stderr_target, true); log_set_print_category_hex(osmo_stderr_target, false); for (i = 0; i < ARRAY_SIZE(log_cats); i++) log_set_category_filter(osmo_stderr_target, log_cats[i], 1, LOGL_DEBUG); } static struct vty_app_info vty_info = { .name = "SccpDemoUser", .version = 0, }; #define DEFAULT_LOCAL_ADDRESS_SERVER "127.0.0.1" #define DEFAULT_LOCAL_ADDRESS_CLIENT "127.0.0.2" #define DEFAULT_REMOTE_ADDRESS_CLIENT DEFAULT_LOCAL_ADDRESS_SERVER #define DEFAULT_REMOTE_ADDRESS_SERVER DEFAULT_LOCAL_ADDRESS_CLIENT #define DEFAULT_LOCAL_PORT_SERVER M3UA_PORT #define DEFAULT_LOCAL_PORT_CLIENT M3UA_PORT #define DEFAULT_REMOTE_PORT_CLIENT DEFAULT_LOCAL_PORT_SERVER #define DEFAULT_REMOTE_PORT_SERVER DEFAULT_LOCAL_PORT_CLIENT #define DEFAULT_PC_SERVER 1 #define DEFAULT_PC_CLIENT 23 static void usage(void) { fprintf(stderr, "sccp_demo_user [-c] [-l LOCAL_ADDRESS[:LOCAL_PORT]]\n" " [-r REMOTE_ADDRESS[:REMOTE_PORT]]\n" " [-L LOCAL_POINT_CODE] [-R REMOTE_POINT_CODE]\n" "Options:\n" " -p: protocol to use (m3ua, sua, ipa; default is m3ua)\n" " -c: Run in client mode (default is server mode)\n" " -C filename The config file to use\n" " -l: local IP address and SCTP port (default is %s:%d in server mode,\n" " %s:%d in client mode)\n" " -r: remote IP address and SCTP port (default is %s:%d in server mode,\n" " %s:%d in client mode)\n" " -L: local point code (default is %d in server mode, %d in client mode)\n" " -R: remote point code (default is %d in server mode, %d in client mode)\n" " -d: LOGMASK (libosmocore log mask string, e.g. -d DLINP,1:DLSS7,2)\n", DEFAULT_LOCAL_ADDRESS_SERVER, DEFAULT_LOCAL_PORT_SERVER, DEFAULT_LOCAL_ADDRESS_CLIENT, DEFAULT_LOCAL_PORT_CLIENT, DEFAULT_REMOTE_ADDRESS_SERVER, DEFAULT_REMOTE_PORT_SERVER, DEFAULT_REMOTE_ADDRESS_CLIENT, DEFAULT_REMOTE_PORT_CLIENT, DEFAULT_PC_SERVER, DEFAULT_PC_CLIENT, DEFAULT_PC_CLIENT, DEFAULT_PC_SERVER); exit(1); } static int is_decimal_string(const char *s) { const char *p = s; if (*p == '\0') return 0; while (*p) { if (!isdigit(*p++)) return 0; } return 1; } static int parse_address_port(char **address, int *port, const char *arg) { char *s, *colon; s = strdup(arg); OSMO_ASSERT(s); colon = strrchr(s, ':'); if (colon) { char *portstr = colon + 1; *colon = '\0'; if (*portstr == '\0') { fprintf(stderr, "missing port number after : in '%s'\n", arg); free(s); return 1; } if (!is_decimal_string(portstr)) { fprintf(stderr, "invalid port number: '%s'\n", portstr); free(s); return 1; } *port = atoi(portstr); } *address = s; return 0; } int main(int argc, char **argv) { bool client = false; int rc, ch; char *local_address = DEFAULT_LOCAL_ADDRESS_SERVER; int local_port = DEFAULT_LOCAL_PORT_SERVER; int local_pc = DEFAULT_PC_SERVER; char *remote_address = DEFAULT_REMOTE_ADDRESS_SERVER; int remote_port = DEFAULT_REMOTE_PORT_SERVER; int remote_pc = DEFAULT_PC_CLIENT; bool lflag = false, rflag = false, Lflag = false, Rflag = false; enum osmo_ss7_asp_protocol protocol = OSMO_SS7_ASP_PROT_M3UA; void *tall_ctx = talloc_named_const(NULL, 1, "sccp_demo_user"); init_logging(tall_ctx); while ((ch = getopt(argc, argv, "p:cl:r:L:R:C:d:")) != -1) { switch (ch) { case 'p': rc = get_string_value(osmo_ss7_asp_protocol_vals, optarg); if (rc < 0) exit(1); protocol = rc; break; case 'c': client = true; /* Set client-mode defaults unless already overridden during option parsing. */ if (!lflag) { local_address = DEFAULT_LOCAL_ADDRESS_CLIENT; local_port = DEFAULT_LOCAL_PORT_CLIENT; } if (!Lflag) local_pc = DEFAULT_PC_CLIENT; if (!rflag) { remote_address = DEFAULT_REMOTE_ADDRESS_CLIENT; remote_port = DEFAULT_REMOTE_PORT_CLIENT; } if (!Rflag) remote_pc = DEFAULT_PC_SERVER; break; case 'l': if (parse_address_port(&local_address, &local_port, optarg)) exit(1); lflag = true; break; case 'r': if (parse_address_port(&remote_address, &remote_port, optarg)) exit(1); rflag = true; break; case 'L': if (!is_decimal_string(optarg)) { fprintf(stderr, "invalid decimal point code: '%s'\n", optarg); exit(1); } local_pc = atoi(optarg); Lflag = true; break; case 'R': if (!is_decimal_string(optarg)) { fprintf(stderr, "invalid decimal point code: '%s'\n", optarg); exit(1); } remote_pc = atoi(optarg); Rflag = true; break; case 'C': config_file = optarg; break; case 'd': log_parse_category_mask(osmo_stderr_target, optarg); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 0) usage(); talloc_enable_leak_report_full(); signal(SIGUSR1, &signal_handler); signal(SIGUSR2, &signal_handler); osmo_stats_init(tall_ctx); rate_ctr_init(tall_ctx); OSMO_ASSERT(osmo_ss7_init() == 0); osmo_fsm_log_addr(false); vty_info.tall_ctx = tall_ctx; vty_init(&vty_info); logging_vty_add_cmds(); osmo_talloc_vty_add_cmds(); osmo_stats_vty_add_cmds(); osmo_fsm_vty_add_cmds(); osmo_ss7_vty_init_asp(NULL); osmo_sccp_vty_init(); /* Read the config if requested with -C */ if (config_file) { rc = vty_read_config_file(config_file, NULL); if (rc < 0) { LOGP(DMAIN, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file); exit(1); } } rc = telnet_init_default(NULL, NULL, 2324 + client); if (rc < 0) { perror("Error binding VTY port"); exit(1); } if (client) { g_sccp = osmo_sccp_simple_client(NULL, "client", local_pc, protocol, local_port, local_address, remote_port, remote_address); if (g_sccp == NULL) { perror("Could not create SCCP client"); exit (1); } sccp_test_user_vty_install(g_sccp, OSMO_SCCP_SSN_BSSAP); } else { g_sccp = sua_server_helper(protocol, local_port, local_address, local_pc, remote_port, remote_address, remote_pc); if (g_sccp == NULL) { perror("Could not create SCCP server"); exit(1); } sccp_test_server_init(g_sccp); sccp_test_user_vty_install(g_sccp, OSMO_SCCP_SSN_BSSAP); } g_calling_addr.pc = local_pc; g_called_addr.pc = remote_pc; while (1) { osmo_select_main(0); } }