diff options
Diffstat (limited to 'src/libmsc/msc_vty.c')
-rw-r--r-- | src/libmsc/msc_vty.c | 220 |
1 files changed, 135 insertions, 85 deletions
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index 9bc8f3aae..f1e2aa107 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -28,6 +28,8 @@ #include <inttypes.h> #include <limits.h> +#include <osmocom/core/use_count.h> + #include <osmocom/gsm/protocol/gsm_08_58.h> #include <osmocom/gsm/protocol/gsm_04_14.h> #include <osmocom/gsm/protocol/gsm_08_08.h> @@ -46,10 +48,11 @@ #include <osmocom/msc/vty.h> #include <osmocom/msc/gsm_data.h> #include <osmocom/msc/gsm_subscriber.h> +#include <osmocom/msc/msub.h> +#include <osmocom/msc/msc_a.h> #include <osmocom/msc/vlr.h> #include <osmocom/msc/transaction.h> #include <osmocom/msc/db.h> -#include <osmocom/msc/a_iface.h> #include <osmocom/msc/sms_queue.h> #include <osmocom/msc/silent_call.h> #include <osmocom/msc/gsm_04_80.h> @@ -59,6 +62,8 @@ #include <osmocom/msc/rrlp.h> #include <osmocom/msc/vlr_sgs.h> #include <osmocom/msc/sgs_vty.h> +#include <osmocom/msc/sccp_ran.h> +#include <osmocom/msc/ran_peer.h> static struct gsm_network *gsmnet = NULL; @@ -504,6 +509,45 @@ DEFUN(cfg_msc_no_sms_over_gsup, cfg_msc_no_sms_over_gsup_cmd, return CMD_SUCCESS; } +DEFUN(cfg_msc_handover_number_range, cfg_msc_handover_number_range_cmd, + "handover-number range MSISDN_FIRST MSISDN_LAST", + "Configure a range of MSISDN to be assigned to incoming inter-MSC Handovers for call forwarding.\n" + "First Handover Number MSISDN\n" + "Last Handover Number MSISDN\n") +{ + char *endp; + uint64_t range_start; + uint64_t range_end; + + /* FIXME leading zeros?? */ + + errno = 0; + range_start = strtoull(argv[0], &endp, 10); + if (errno || *endp != '\0') { + vty_out(vty, "%% Error parsing handover-number range start: %s%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + errno = 0; + range_end = strtoull(argv[1], &endp, 10); + if (errno || *endp != '\0') { + vty_out(vty, "%% Error parsing handover-number range end: %s%s", + argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + + if (range_start > range_end) { + vty_out(vty, "%% Error: handover-number range end must be > than the range start, but" + " %"PRIu64" > %"PRIu64"%s", range_start, range_end, VTY_NEWLINE); + return CMD_WARNING; + } + + gsmnet->handover_number.range_start = range_start; + gsmnet->handover_number.range_end = range_end; + return CMD_SUCCESS; +} + static int config_write_msc(struct vty *vty) { vty_out(vty, "msc%s", VTY_NEWLINE); @@ -546,6 +590,11 @@ static int config_write_msc(struct vty *vty) if (gsmnet->sms_over_gsup) vty_out(vty, " sms-over-gsup%s", VTY_NEWLINE); + if (gsmnet->handover_number.range_start || gsmnet->handover_number.range_end) + vty_out(vty, " handover-number range %"PRIu64" %"PRIu64"%s", + gsmnet->handover_number.range_start, gsmnet->handover_number.range_end, + VTY_NEWLINE); + mgcp_client_config_write(vty, " "); #ifdef BUILD_IU ranap_iu_vty_config_write(vty, " "); @@ -557,81 +606,81 @@ static int config_write_msc(struct vty *vty) DEFUN(show_bsc, show_bsc_cmd, "show bsc", SHOW_STR "BSC\n") { - struct bsc_context *bsc_ctx; - struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(gsmnet->a.cs7_instance); - - llist_for_each_entry(bsc_ctx, &gsmnet->a.bscs, list) { - vty_out(vty, "BSC %s%s", osmo_sccp_addr_name(ss7, &bsc_ctx->bsc_addr), VTY_NEWLINE); + struct ran_peer *rp; + llist_for_each_entry(rp, &gsmnet->a.sri->ran_peers, entry) { + vty_out(vty, "BSC %s %s%s", + osmo_sccp_inst_addr_name(gsmnet->a.sri->sccp, &rp->peer_addr), + osmo_fsm_inst_state_name(rp->fi), + VTY_NEWLINE); } return CMD_SUCCESS; } -static void vty_conn_hdr(struct vty *vty) +/* +_Subscriber_______________________________________ _LAC_ _RAN___________________ _MSC-A_state_________ _MSC-A_use_ +IMSI-123456789012345:MSISDN-12345:TMSI-0x12345678 1 GERAN-A-4294967295:A5-3 WAIT_CLASSMARK_UPDATE 2=cm_service,trans_cc +IMSI-123456789012356:MSISDN-234567:TMSI-0x123ABC78 65535 UTRAN-Iu-4294967295 COMMUNICATING 2=cm_service,trans_sms +IMSI-123456789012367:MSISDN-98712345890:TMSI-0xF.. - EUTRAN-SGs RELEASING 0=none +IMSI-123456789012378:HONR-12345432101 2 MSC-901-700-423:9876 REMOTE_MSC_A 1=inter_msc +*/ +static void vty_dump_one_conn(struct vty *vty, const struct msub *msub, int *idx) { - unsigned lnum = 0; - struct ran_conn *conn; - - llist_for_each_entry(conn, &gsmnet->ran_conns, entry) - lnum++; + struct msc_a *msc_a = msub_msc_a(msub); + struct vlr_subscr *vsub = msub_vsub(msub); + char buf[128]; - if (lnum) - vty_out(vty, "--ConnId RAN --LAC Use --Tokens C A5 State ------------ Subscriber%s", + if (!(*idx)) + vty_out(vty, + "_Subscriber_______________________________________ _LAC_ _RAN___________________" + " _MSC-A_state_________ _MSC-A_use_%s", VTY_NEWLINE); -} - -static void vty_dump_one_conn(struct vty *vty, const struct ran_conn *conn) -{ - vty_out(vty, "%08x %3s %5u %3u %08x %c /%1u %27s %22s%s", - conn->a.conn_id, - osmo_rat_type_name(conn->via_ran), - conn->lac, - conn->use_count, - conn->use_tokens, - conn->received_cm_service_request ? 'C' : '-', - conn->geran_encr.alg_id, - conn->fi ? osmo_fsm_inst_state_name(conn->fi) : "-", - conn->vsub ? vlr_subscr_name(conn->vsub) : "-", + (*idx)++; + + vty_out(vty, "%50s %5u %23s %20s %d=%s%s", + vlr_subscr_short_name(msub_vsub(msub), 50), + vsub ? vsub->cgi.lai.lac : 0, + msub_ran_conn_name(msub), + osmo_fsm_inst_state_name(msc_a->c.fi), + osmo_use_count_total(&msc_a->use_count), + osmo_use_count_name_buf(buf, sizeof(buf), &msc_a->use_count), VTY_NEWLINE); } DEFUN(show_msc_conn, show_msc_conn_cmd, "show connection", SHOW_STR "Subscriber Connections\n") { - struct ran_conn *conn; - - vty_conn_hdr(vty); - llist_for_each_entry(conn, &gsmnet->ran_conns, entry) - vty_dump_one_conn(vty, conn); - + struct msub *msub; + int idx = 0; + llist_for_each_entry(msub, &msub_list, entry) { + vty_dump_one_conn(vty, msub, &idx); + } return CMD_SUCCESS; } static void vty_trans_hdr(struct vty *vty) { - unsigned lnum = 0; - struct gsm_trans *trans; + if (llist_empty(&gsmnet->trans_list)) + return; - llist_for_each_entry(trans, &gsmnet->trans_list, entry) - lnum++; - - if (lnum) - vty_out(vty, "--ConnId -P TI -CallRef [--- Proto ---] ------------ Subscriber%s", - VTY_NEWLINE); + vty_out(vty, + "_Subscriber_______________________________________ _RAN___________________" + " _P__ TI CallRef_ _state_%s", + VTY_NEWLINE); } static const char *get_trans_proto_str(const struct gsm_trans *trans) { static char buf[256]; - switch (trans->protocol) { - case GSM48_PDISC_CC: + switch (trans->type) { + case TRANS_CC: snprintf(buf, sizeof(buf), "%s %4u %4u", gsm48_cc_state_name(trans->cc.state), trans->cc.Tcurrent, trans->cc.T308_second); break; - case GSM48_PDISC_SMS: + case TRANS_SMS: snprintf(buf, sizeof(buf), "%s %s", gsm411_cp_state_name(trans->sms.smc_inst.cp_state), gsm411_rp_state_name(trans->sms.smr_inst.rp_state)); @@ -646,13 +695,13 @@ static const char *get_trans_proto_str(const struct gsm_trans *trans) static void vty_dump_one_trans(struct vty *vty, const struct gsm_trans *trans) { - vty_out(vty, "%08x %s %02u %08x [%s] %22s%s", - trans->conn ? trans->conn->a.conn_id : 0, - gsm48_pdisc_name(trans->protocol), + vty_out(vty, "%50s %23s %4s %02u %08x %s%s", + vlr_subscr_short_name(msc_a_vsub(trans->msc_a), 50), + msub_ran_conn_name(trans->msc_a->c.msub), + trans_type_name(trans->type), trans->transaction_id, trans->callref, get_trans_proto_str(trans), - trans->vsub ? vlr_subscr_name(trans->vsub) : "-", VTY_NEWLINE); } @@ -715,18 +764,6 @@ static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub) vty_out(vty, " LA allowed: %s%s", vsub->la_allowed ? "true" : "false", VTY_NEWLINE); -#if 0 - /* TODO: add this to vlr_subscr? */ - if (vsub->auth_info.auth_algo != AUTH_ALGO_NONE) { - struct gsm_auth_info *i = &vsub->auth_info; - vty_out(vty, " A3A8 algorithm id: %d%s", - i->auth_algo, VTY_NEWLINE); - vty_out(vty, " A3A8 Ki: %s%s", - osmo_hexdump(i->a3a8_ki, i->a3a8_ki_len), - VTY_NEWLINE); - } -#endif - if (vsub->last_tuple) { struct vlr_auth_tuple *t = vsub->last_tuple; vty_out(vty, " A3A8 last tuple (used %d times):%s", @@ -762,9 +799,11 @@ static void subscr_dump_full_vty(struct vty *vty, struct vlr_subscr *vsub) /* Connection */ if (vsub->msc_conn_ref) { - struct ran_conn *conn = vsub->msc_conn_ref; - vty_conn_hdr(vty); - vty_dump_one_conn(vty, conn); + struct msub *msub = vsub->msc_conn_ref; + int idx = 0; + if (msub) { + vty_dump_one_conn(vty, msub, &idx); + } } /* Transactions */ @@ -1214,7 +1253,7 @@ DEFUN(subscriber_ussd_notify, "Text of USSD message to send\n") { char *text; - struct ran_conn *conn; + struct msc_a *msc_a; struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]); int level; @@ -1231,19 +1270,19 @@ DEFUN(subscriber_ussd_notify, return CMD_WARNING; } - conn = connection_for_subscr(vsub); - if (!conn) { - vty_out(vty, "%% An active connection is required for %s %s%s", + msc_a = msc_a_for_vsub(vsub, true); + if (!msc_a || msc_a->c.remote_to) { + vty_out(vty, "%% An active connection and local MSC-A role is required for %s %s%s", argv[0], argv[1], VTY_NEWLINE); vlr_subscr_put(vsub, VSUB_USE_VTY); talloc_free(text); return CMD_WARNING; } - msc_send_ussd_notify(conn, level, text); + msc_send_ussd_notify(msc_a, level, text); /* FIXME: since we don't allocate a transaction here, * we use dummy GSM 04.07 transaction ID. */ - msc_send_ussd_release_complete(conn, 0x00); + msc_send_ussd_release_complete(msc_a, 0x00); vlr_subscr_put(vsub, VSUB_USE_VTY); talloc_free(text); @@ -1256,7 +1295,7 @@ DEFUN(subscriber_paging, SUBSCR_HELP "Issue an empty Paging for the subscriber (for debugging)\n") { struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]); - struct subscr_request *req; + struct paging_request *req; if (!vsub) { vty_out(vty, "%% No subscriber found for %s %s%s", @@ -1264,7 +1303,8 @@ DEFUN(subscriber_paging, return CMD_WARNING; } - req = subscr_request_conn(vsub, NULL, NULL, "manual Paging from VTY", SGSAP_SERV_IND_CS_CALL); + req = paging_request_start(vsub, PAGING_CAUSE_CALL_CONVERSATIONAL, + NULL, NULL, "manual Paging from VTY"); if (req) vty_out(vty, "%% paging subscriber%s", VTY_NEWLINE); else @@ -1308,7 +1348,7 @@ DEFUN(subscriber_mstest_close, "Loop Type F\n" "Loop Type I\n") { - struct ran_conn *conn; + struct msc_a *msc_a; struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]); const char *loop_str; int loop_mode; @@ -1322,15 +1362,15 @@ DEFUN(subscriber_mstest_close, loop_str = argv[2]; loop_mode = loop_by_char(loop_str[0]); - conn = connection_for_subscr(vsub); - if (!conn) { + msc_a = msc_a_for_vsub(vsub, true); + if (!msc_a) { vty_out(vty, "%% An active connection is required for %s %s%s", argv[0], argv[1], VTY_NEWLINE); vlr_subscr_put(vsub, VSUB_USE_VTY); return CMD_WARNING; } - gsm0414_tx_close_tch_loop_cmd(conn, loop_mode); + gsm0414_tx_close_tch_loop_cmd(msc_a, loop_mode); return CMD_SUCCESS; } @@ -1341,7 +1381,7 @@ DEFUN(subscriber_mstest_open, SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n" "Open a TCH Loop inside the MS\n") { - struct ran_conn *conn; + struct msc_a *msc_a; struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]); if (!vsub) { @@ -1350,15 +1390,15 @@ DEFUN(subscriber_mstest_open, return CMD_WARNING; } - conn = connection_for_subscr(vsub); - if (!conn) { + msc_a = msc_a_for_vsub(vsub, true); + if (!msc_a) { vty_out(vty, "%% An active connection is required for %s %s%s", argv[0], argv[1], VTY_NEWLINE); vlr_subscr_put(vsub, VSUB_USE_VTY); return CMD_WARNING; } - gsm0414_tx_open_loop_cmd(conn); + gsm0414_tx_open_loop_cmd(msc_a); return CMD_SUCCESS; } @@ -1394,14 +1434,20 @@ static int scall_cbfn(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct scall_signal_data *sigdata = signal_data; - struct vty *vty = sigdata->data; + struct vty *vty = sigdata->vty; + + if (!vty_is_active(vty)) + return 0; switch (signal) { case S_SCALL_SUCCESS: - vty_out(vty, "%% silent call success%s", VTY_NEWLINE); + vty_out(vty, "%% Silent call success%s", VTY_NEWLINE); + break; + case S_SCALL_FAILED: + vty_out(vty, "%% Silent call failed%s", VTY_NEWLINE); break; - case S_SCALL_EXPIRED: - vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE); + case S_SCALL_DETACHED: + vty_out(vty, "%% Silent call ended%s", VTY_NEWLINE); break; } return 0; @@ -1692,12 +1738,16 @@ void msc_vty_init(struct gsm_network *msc_network) install_element(MSC_NODE, &cfg_msc_emergency_msisdn_cmd); install_element(MSC_NODE, &cfg_msc_sms_over_gsup_cmd); install_element(MSC_NODE, &cfg_msc_no_sms_over_gsup_cmd); + install_element(MSC_NODE, &cfg_msc_handover_number_range_cmd); + + neighbor_ident_vty_init(msc_network); mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf); #ifdef BUILD_IU - ranap_iu_vty_init(MSC_NODE, &msc_network->iu.rab_assign_addr_enc); + ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc); #endif sgs_vty_init(); + osmo_fsm_vty_add_cmds(); osmo_signal_register_handler(SS_SCALL, scall_cbfn, NULL); |