aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-10-27 11:01:55 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-10-27 11:01:55 +0200
commit54f5352e0777c6407b47b5d7f9ab366f66179e48 (patch)
tree28ab7e0485956c673c60dce2075406c7b5ba708b
parent07dfc702764d2a148ce6e6c8869f76f47170f072 (diff)
nat: Close SCCP connections when the USSD Provider is closed.
Send a RLSD down to the BSC in case the USSD Provider is gone. It is not sending a Clear Command and ut depends if the BS+ will like this kind of behavior. At least the data on the NAT will be freed soon afterwards due the RLC message.
-rw-r--r--openbsc/include/openbsc/bsc_nat.h1
-rw-r--r--openbsc/src/nat/bsc_nat.c37
-rw-r--r--openbsc/src/nat/bsc_ussd.c5
3 files changed, 42 insertions, 1 deletions
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 57818992f..e1d2f3219 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -231,6 +231,27 @@ static void nat_send_rlsd_msc(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_rlc(struct bsc_msc_connection *msc_con,
struct sccp_source_reference *src,
struct sccp_source_reference *dst)
@@ -1307,3 +1328,19 @@ 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_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);