aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/bsc_msc_ip.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-29 10:09:27 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-29 10:09:27 +0200
commitf0b21dfd25db613f30c4752b26a14bbaeffd2e1e (patch)
treecf6b80c45b09faff911d58ba73dba1be907dc4c2 /openbsc/src/bsc_msc_ip.c
parente165d1aaa4abecbb8642139ee53d4f6e28ec0b00 (diff)
bsc_msc: Handle the loss of the MSC connection better
Instead of simply exiting the application we will handle it by giving up all SCCP connections, once we have the MSC back we will send a GSM 08.08 reset message, and we will free all resources related to these connections. This includes the primary and secondary lchan of these connections. While we are not connected to the MSC we will handle each message that would open a SCCP connection by giving up the lchan. This has only been compile tested and will need to be manually tested during a test session. This also highlights a DoS that could be used against OpenBSC by setting up a lchan but never send any GSM L3 message. We will have to fix that at some point.
Diffstat (limited to 'openbsc/src/bsc_msc_ip.c')
-rw-r--r--openbsc/src/bsc_msc_ip.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c
index 5dc05c357..01f45c40c 100644
--- a/openbsc/src/bsc_msc_ip.c
+++ b/openbsc/src/bsc_msc_ip.c
@@ -193,12 +193,20 @@ void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
* IMMEDIATE SETUP is coming from GROUP CC that is not yet
* supported...
*/
-int open_sccp_connection(struct msgb *layer3)
+static int open_sccp_connection(struct msgb *layer3)
{
struct bss_sccp_connection_data *con_data;
struct sccp_connection *sccp_connection;
struct msgb *data;
+ /* When not connected to a MSC. We will simply close things down. */
+ if (!msc_con->is_connected) {
+ LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
+ use_lchan(layer3->lchan);
+ put_lchan(layer3->lchan, 0);
+ return -1;
+ }
+
DEBUGP(DMSC, "Opening new layer3 connection\n");
sccp_connection = sccp_connection_socket();
if (!sccp_connection) {
@@ -650,11 +658,36 @@ static void send_id_get_response(int fd)
* The connection to the MSC was lost and we will need to free all
* resources and then attempt to reconnect.
*/
-static void msc_connection_was_lost(struct bsc_msc_connection *con)
+static void msc_connection_was_lost(struct bsc_msc_connection *msc)
{
- LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freeing information.\n");
+ struct bss_sccp_connection_data *bss, *tmp;
+
+ LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freing stuff.\n");
+
+ llist_for_each_entry_safe(bss, tmp, &active_connections, active_connections) {
+ if (bss->lchan) {
+ bss->lchan->msc_data = NULL;
+ put_lchan(bss->lchan, 0);
+ bss->lchan = NULL;
+ }
+
+ if (bss->secondary_lchan) {
+ bss->secondary_lchan->msc_data = NULL;
+ put_lchan(bss->secondary_lchan, 0);
+ bss->secondary_lchan = NULL;
+ }
+
+ /* force the close by poking stuff */
+ if (bss->sccp) {
+ bss->sccp->connection_state = SCCP_CONNECTION_STATE_REFUSED;
+ sccp_connection_free(bss->sccp);
+ bss->sccp = NULL;
+ }
+
+ bss_sccp_free_data(bss);
+ }
- exit(0);
+ bsc_msc_schedule_connect(msc);
}
/*
@@ -669,6 +702,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
if (!msg) {
if (error == 0) {
LOGP(DMSC, LOGL_ERROR, "The connection to the MSC was lost.\n");
+ bsc_msc_lost(msc_con);
return -1;
}