aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-12-27 13:46:48 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-12-27 14:12:12 +0100
commit3a2453cad1837a6990a2c0b36bd21df11a50d87d (patch)
treece1ce485e4a14e439540e302ea8d156d16019b3e
parent5eea1f8c20be88eec69ec7d9d7ed005098a70937 (diff)
bsc: Clear the hand-over in case the new_lchan is failing
When the new_lchan for handover is failing we should stop the handover operation. This is fixing a crash that we get a timeout on the lchan and have no conn set to it. Introduce a flag to the bsc_clear_handover to not free the lchan. In case the ho_lchan is failing we do not want to call lchan_release as it would reset the state.
-rw-r--r--openbsc/include/openbsc/handover.h2
-rw-r--r--openbsc/src/bsc_api.c6
-rw-r--r--openbsc/src/handover_logic.c6
3 files changed, 9 insertions, 5 deletions
diff --git a/openbsc/include/openbsc/handover.h b/openbsc/include/openbsc/handover.h
index 5d710576c..9d9a90b84 100644
--- a/openbsc/include/openbsc/handover.h
+++ b/openbsc/include/openbsc/handover.h
@@ -9,6 +9,6 @@ struct gsm_subscriber_connection;
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
/* clear any operation for this connection */
-void bsc_clear_handover(struct gsm_subscriber_connection *conn);
+void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
#endif /* _HANDOVER_H */
diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c
index a91de66f7..44db39f1c 100644
--- a/openbsc/src/bsc_api.c
+++ b/openbsc/src/bsc_api.c
@@ -521,7 +521,7 @@ int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
int gsm0808_clear(struct gsm_subscriber_connection *conn)
{
if (conn->ho_lchan)
- bsc_clear_handover(conn);
+ bsc_clear_handover(conn, 1);
if (conn->secondary_lchan)
lchan_release(conn->secondary_lchan, 0, 1);
@@ -634,8 +634,10 @@ static void handle_release(struct gsm_subscriber_connection *conn,
/* now give up all channels */
if (conn->lchan == lchan)
conn->lchan = NULL;
- if (conn->ho_lchan == lchan)
+ if (conn->ho_lchan == lchan) {
+ bsc_clear_handover(conn, 0);
conn->ho_lchan = NULL;
+ }
lchan->conn = NULL;
gsm0808_clear(conn);
diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c
index d04c0eb64..22949dbd5 100644
--- a/openbsc/src/handover_logic.c
+++ b/openbsc/src/handover_logic.c
@@ -149,7 +149,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
return 0;
}
-void bsc_clear_handover(struct gsm_subscriber_connection *conn)
+void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan)
{
struct bsc_handover *ho;
@@ -166,7 +166,9 @@ void bsc_clear_handover(struct gsm_subscriber_connection *conn)
conn->ho_lchan->conn = NULL;
conn->ho_lchan = NULL;
- lchan_release(ho->new_lchan, 0, 1);
+
+ if (free_lchan)
+ lchan_release(ho->new_lchan, 0, 1);
bsc_del_timer(&ho->T3103);
llist_del(&ho->list);