diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-03-29 10:09:27 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-03-29 10:09:27 +0200 |
commit | f0b21dfd25db613f30c4752b26a14bbaeffd2e1e (patch) | |
tree | cf6b80c45b09faff911d58ba73dba1be907dc4c2 /openbsc/src/bsc_msc_ip.c | |
parent | e165d1aaa4abecbb8642139ee53d4f6e28ec0b00 (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.c | 42 |
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; } |