diff options
-rw-r--r-- | openbsc/configure.in | 2 | ||||
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 1 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 64 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_ussd.c | 5 |
4 files changed, 68 insertions, 4 deletions
diff --git a/openbsc/configure.in b/openbsc/configure.in index c0ec3cde0..f98bb709e 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -43,7 +43,7 @@ AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo B ]) AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes") -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.24) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.27) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.19) dnl checks for header files diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h index acecba7de..7c7dde323 100644 --- a/openbsc/include/openbsc/bsc_nat.h +++ b/openbsc/include/openbsc/bsc_nat.h @@ -337,5 +337,6 @@ struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *ms /** USSD filtering */ int bsc_ussd_init(struct bsc_nat *nat); int bsc_check_ussd(struct sccp_connections *con, struct bsc_nat_parsed *parsed, struct msgb *msg); +int bsc_close_ussd_connections(struct bsc_nat *nat); #endif diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index daabf0976..a428e823d 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -208,7 +208,7 @@ static void send_id_req(struct bsc_connection *bsc) bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS); } -static void nat_send_rlsd(struct sccp_connections *conn) +static void nat_send_rlsd_msc(struct sccp_connections *conn) { struct sccp_connection_released *rel; struct msgb *msg; @@ -231,6 +231,49 @@ static void nat_send_rlsd(struct sccp_connections *conn) queue_for_msc(conn->msc_con, msg); } +static void nat_send_rlsd_bsc(struct sccp_connections *conn) +{ + struct sccp_connection_released *rel; + struct msgb *msg; + + msg = msgb_alloc_headroom(4096, 128, "rlsd"); + if (!msg) { + LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n"); + return; + } + + msg->l2h = msgb_put(msg, sizeof(*rel)); + rel = (struct sccp_connection_released *) msg->l2h; + rel->type = SCCP_MSG_TYPE_RLSD; + rel->release_cause = SCCP_RELEASE_CAUSE_SCCP_FAILURE; + rel->destination_local_reference = conn->real_ref; + rel->source_local_reference = conn->remote_ref; + + bsc_write(conn->bsc, msg, IPAC_PROTO_SCCP); +} + +static void nat_send_clrc_bsc(struct sccp_connections *conn) +{ + struct msgb *msg; + struct msgb *sccp; + + msg = gsm0808_create_clear_command(0x20); + if (!msg) { + LOGP(DNAT, LOGL_ERROR, "Failed to allocate clear command.\n"); + return; + } + + sccp = sccp_create_dt1(&conn->real_ref, msg->data, msg->len); + if (!sccp) { + LOGP(DNAT, LOGL_ERROR, "Failed to allocate SCCP msg.\n"); + msgb_free(msg); + return; + } + + msgb_free(msg); + bsc_write(conn->bsc, sccp, IPAC_PROTO_SCCP); +} + static void nat_send_rlc(struct bsc_msc_connection *msc_con, struct sccp_source_reference *src, struct sccp_source_reference *dst) @@ -709,7 +752,7 @@ void bsc_close_connection(struct bsc_connection *connection) if (ctr) rate_ctr_inc(ctr); if (sccp_patch->has_remote_ref && !sccp_patch->con_local) - nat_send_rlsd(sccp_patch); + nat_send_rlsd_msc(sccp_patch); sccp_connection_destroy(sccp_patch); } @@ -1307,3 +1350,20 @@ int main(int argc, char **argv) return 0; } + +/* Close all connections handed out to the USSD module */ +int bsc_close_ussd_connections(struct bsc_nat *nat) +{ + struct sccp_connections *con; + llist_for_each_entry(con, &nat->sccp_connections, list_entry) { + if (con->con_local != 2) + continue; + if (!con->bsc) + continue; + + nat_send_clrc_bsc(con); + nat_send_rlsd_bsc(con); + } + + return 0; +} diff --git a/openbsc/src/nat/bsc_ussd.c b/openbsc/src/nat/bsc_ussd.c index 3729d91f3..f10a871ab 100644 --- a/openbsc/src/nat/bsc_ussd.c +++ b/openbsc/src/nat/bsc_ussd.c @@ -61,8 +61,11 @@ static struct bsc_nat_ussd_con *bsc_nat_ussd_alloc(struct bsc_nat *nat) static void bsc_nat_ussd_destroy(struct bsc_nat_ussd_con *con) { - if (con->nat->ussd_con == con) + if (con->nat->ussd_con == con) { + bsc_close_ussd_connections(con->nat); con->nat->ussd_con = NULL; + } + close(con->queue.bfd.fd); bsc_unregister_fd(&con->queue.bfd); bsc_del_timer(&con->auth_timeout); |