diff options
-rw-r--r-- | include/osmocom/msc/gsm_data.h | 2 | ||||
-rw-r--r-- | include/osmocom/msc/transaction.h | 2 | ||||
-rw-r--r-- | src/libmsc/gsm_09_11.c | 62 | ||||
-rw-r--r-- | src/libmsc/msc_vty.c | 15 | ||||
-rw-r--r-- | src/libmsc/osmo_msc.c | 1 | ||||
-rw-r--r-- | tests/test_nodes.vty | 8 |
6 files changed, 90 insertions, 0 deletions
diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h index dab082d82..7d3a1e71b 100644 --- a/include/osmocom/msc/gsm_data.h +++ b/include/osmocom/msc/gsm_data.h @@ -192,6 +192,8 @@ struct gsm_network { /* Global MNCC guard timer value */ int mncc_guard_timeout; + /* Global guard timer value for NCSS sessions */ + int ncss_guard_timeout; struct { struct mgcp_client_conf conf; diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 39b09aeaa..830328bca 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -87,6 +87,8 @@ struct gsm_trans { * a subscriber after successful Paging Response */ struct msgb *msg; + /* Inactivity timer, triggers transaction release */ + struct osmo_timer_list timer_guard; } ss; }; diff --git a/src/libmsc/gsm_09_11.c b/src/libmsc/gsm_09_11.c index d2ad0b7a6..c133656dd 100644 --- a/src/libmsc/gsm_09_11.c +++ b/src/libmsc/gsm_09_11.c @@ -51,6 +51,39 @@ /* FIXME: choose a proper range */ static uint32_t new_callref = 0x20000001; +static void ncss_session_timeout_handler(void *_trans) +{ + struct gsm_trans *trans = (struct gsm_trans *) _trans; + struct osmo_gsup_message gsup_msg = { 0 }; + + /* The timeout might be disabled from the VTY */ + if (trans->net->ncss_guard_timeout == 0) + return; + + LOGP(DMM, LOGL_NOTICE, "SS/USSD session timeout, releasing " + "transaction (trans=%p, callref=%x)\n", trans, trans->callref); + + /* Indicate connection release to subscriber (if active) */ + if (trans->conn != NULL) { + /* This pair of cause location and value is used by commercial networks */ + msc_send_ussd_release_complete_cause(trans->conn, trans->transaction_id, + GSM48_CAUSE_LOC_PUN_S_LU, GSM48_CC_CAUSE_NORMAL_UNSPEC); + } + + /* Terminate GSUP session with EUSE */ + gsup_msg.message_type = OSMO_GSUP_MSGT_PROC_SS_ERROR; + OSMO_STRLCPY_ARRAY(gsup_msg.imsi, trans->vsub->imsi); + + gsup_msg.session_state = OSMO_GSUP_SESSION_STATE_END; + gsup_msg.session_id = trans->callref; + gsup_msg.cause = GMM_CAUSE_NET_FAIL; + + osmo_gsup_client_enc_send(trans->net->vlr->gsup_client, &gsup_msg); + + /* Finally, release this transaction */ + trans_free(trans); +} + /* Entry point for call independent MO SS messages */ int gsm0911_rcv_nc_ss(struct ran_conn *conn, struct msgb *msg) { @@ -108,6 +141,10 @@ int gsm0911_rcv_nc_ss(struct ran_conn *conn, struct msgb *msg) return -ENOMEM; } + /* Init inactivity timer */ + osmo_timer_setup(&trans->ss.timer_guard, + ncss_session_timeout_handler, trans); + /* Count active NC SS/USSD sessions */ osmo_counter_inc(conn->network->active_nc_ss); @@ -116,6 +153,12 @@ int gsm0911_rcv_nc_ss(struct ran_conn *conn, struct msgb *msg) cm_service_request_concludes(conn, msg); } + /* (Re)schedule the inactivity timer */ + if (conn->network->ncss_guard_timeout > 0) { + osmo_timer_schedule(&trans->ss.timer_guard, + conn->network->ncss_guard_timeout, 0); + } + /* Attempt to extract Facility IE */ rc = gsm0480_extract_ie_by_tag(gh, msgb_l3len(msg), &facility_ie, &facility_ie_len, GSM0480_IE_FACILITY); @@ -233,6 +276,12 @@ static int handle_paging_event(unsigned int hooknum, unsigned int event, transt->conn = ran_conn_get(conn, RAN_CONN_USE_TRANS_NC_SS); transt->paging_request = NULL; + /* (Re)schedule the inactivity timer */ + if (conn->network->ncss_guard_timeout > 0) { + osmo_timer_schedule(&transt->ss.timer_guard, + conn->network->ncss_guard_timeout, 0); + } + /* Send stored message */ ss_msg = transt->ss.msg; gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh)); @@ -317,6 +366,10 @@ static struct gsm_trans *establish_nc_ss_trans(struct gsm_network *net, } trans->transaction_id = tid; + /* Init inactivity timer */ + osmo_timer_setup(&trans->ss.timer_guard, + ncss_session_timeout_handler, trans); + /* Attempt to find connection */ conn = connection_for_subscr(vsub); if (conn) { @@ -371,6 +424,9 @@ void _gsm911_nc_ss_trans_free(struct gsm_trans *trans) if (trans->ss.msg != NULL) msgb_free(trans->ss.msg); + /* Stop inactivity timer */ + osmo_timer_del(&trans->ss.timer_guard); + /* One session less */ osmo_counter_dec(trans->net->active_nc_ss); } @@ -420,6 +476,12 @@ int gsm0911_gsup_handler(struct vlr_subscr *vsub, return 0; } + /* (Re)schedule the inactivity timer */ + if (net->ncss_guard_timeout > 0) { + osmo_timer_schedule(&trans->ss.timer_guard, + net->ncss_guard_timeout, 0); + } + /* Allocate and prepare a new MT message */ ss_msg = gsm48_msgb_alloc_name("GSM 04.08 SS/USSD"); gh = (struct gsm48_hdr *) msgb_push(ss_msg, sizeof(*gh)); diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index 078b83aea..5aa533b1f 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -375,6 +375,18 @@ ALIAS_DEPRECATED(cfg_msc_mncc_guard_timeout, "mncc-guard-timeout <0-255>", MNCC_GUARD_TIMEOUT_STR MNCC_GUARD_TIMEOUT_VALUE_STR); +#define NCSS_STR "Configure call independent Supplementary Services\n" + +DEFUN(cfg_msc_ncss_guard_timeout, + cfg_msc_ncss_guard_timeout_cmd, + "ncss guard-timeout <0-255>", + NCSS_STR "Set guard timer for session activity\n" + "guard timer value (sec.), or 0 to disable\n") +{ + gsmnet->ncss_guard_timeout = atoi(argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_msc_assign_tmsi, cfg_msc_assign_tmsi_cmd, "assign-tmsi", "Assign TMSI during Location Updating.\n") @@ -496,6 +508,8 @@ static int config_write_msc(struct vty *vty) vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE); vty_out(vty, " mncc guard-timeout %i%s", gsmnet->mncc_guard_timeout, VTY_NEWLINE); + vty_out(vty, " ncss guard-timeout %i%s", + gsmnet->ncss_guard_timeout, VTY_NEWLINE); vty_out(vty, " %sassign-tmsi%s", gsmnet->vlr->cfg.assign_tmsi? "" : "no ", VTY_NEWLINE); @@ -1588,6 +1602,7 @@ void msc_vty_init(struct gsm_network *msc_network) install_element(MSC_NODE, &cfg_msc_mncc_external_cmd); install_element(MSC_NODE, &cfg_msc_mncc_guard_timeout_cmd); install_element(MSC_NODE, &cfg_msc_deprecated_mncc_guard_timeout_cmd); + install_element(MSC_NODE, &cfg_msc_ncss_guard_timeout_cmd); install_element(MSC_NODE, &cfg_msc_no_assign_tmsi_cmd); install_element(MSC_NODE, &cfg_msc_auth_tuple_max_reuse_count_cmd); install_element(MSC_NODE, &cfg_msc_auth_tuple_reuse_on_error_cmd); diff --git a/src/libmsc/osmo_msc.c b/src/libmsc/osmo_msc.c index 9828da164..5c6f0aa2e 100644 --- a/src/libmsc/osmo_msc.c +++ b/src/libmsc/osmo_msc.c @@ -54,6 +54,7 @@ struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv) net->t3212 = 5; net->mncc_guard_timeout = 180; + net->ncss_guard_timeout = 30; net->paging_response_timer = MSC_PAGING_RESPONSE_TIMER_DEFAULT; diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty index f2312d144..fb9e5f051 100644 --- a/tests/test_nodes.vty +++ b/tests/test_nodes.vty @@ -34,6 +34,7 @@ OsmoMSC(config-msc)# list mncc internal mncc external MNCC_SOCKET_PATH mncc guard-timeout <0-255> + ncss guard-timeout <0-255> no assign-tmsi auth-tuple-max-reuse-count <-1-2147483647> auth-tuple-reuse-on-error (0|1) @@ -50,6 +51,12 @@ OsmoMSC(config-msc)# list mgw remote-port <0-65535> ... +OsmoMSC(config-msc)# ncss? + ncss Configure call independent Supplementary Services + +OsmoMSC(config-msc)# ncss ? + guard-timeout Set guard timer for session activity + OsmoMSC(config-msc)# mncc? mncc Configure Mobile Network Call Control @@ -123,6 +130,7 @@ network periodic location update 30 msc mncc guard-timeout 180 + ncss guard-timeout 30 assign-tmsi cs7-instance-a 0 ... |