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.
This commit is contained in:
Holger Hans Peter Freyther 2010-03-29 10:09:27 +02:00
parent e165d1aaa4
commit f0b21dfd25
1 changed files with 38 additions and 4 deletions

View File

@ -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;
exit(0);
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);
}
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;
}