From 459720a96d868e31b8ab859fdf488c1c208b2647 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Thu, 24 Jan 2013 16:14:18 +0100 Subject: l2tp: Fix PPP session disconnection When a PPP session terminates on its own (i.e. not on behalf of a L2TP tunnel/session request), the l2tp_ppp_finished() callback calls the L2TP session disconnection function without updating the session's state. Session disconnection code then works like if the PPP session was still up: it tries to disconnect the PPP by calling ap_session_terminate(). But since the PPP is already terminated, it returns immediately, without calling the l2tp_ppp_finished() callback; so session cleanup won't happen. This patch updates the session's state upon PPP disconnection, so that the session disconnection code won't try to disconnect the PPP in __l2tp_session_free(). The stat_active counter is now updated inside the l2tp_ppp_finished() callback so that it gets called upon any PPP disconnection. Sending of the EV_CTRL_FINISHED event has also been moved. It is now performed in the generic part of __l2tp_session_free() because it has to be done every time the session really terminates. Signed-off-by: Guillaume Nault --- accel-pppd/ctrl/l2tp/l2tp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'accel-pppd/ctrl') diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index f09aaed..4292aca 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -235,11 +235,9 @@ static void __l2tp_session_free(void *data) switch (sess->state1) { case STATE_PPP: - __sync_sub_and_fetch(&stat_active, 1); sess->state1 = STATE_CLOSE; ap_session_terminate(&sess->ppp.ses, TERM_USER_REQUEST, 1); - triton_event_fire(EV_CTRL_FINISHED, &sess->ppp.ses); /* No cleanup here, "sess" must remain a valid session pointer (even if it no l2tp_conn_t points to it anymore). This is because the above call to ap_session_terminate() @@ -252,10 +250,11 @@ static void __l2tp_session_free(void *data) case STATE_WAIT_ICCN: case STATE_ESTB: __sync_sub_and_fetch(&stat_starting, 1); - triton_event_fire(EV_CTRL_FINISHED, &sess->ppp.ses); break; } + triton_event_fire(EV_CTRL_FINISHED, &sess->ppp.ses); + log_ppp_info1("disconnected\n"); triton_context_unregister(&sess->sctx); @@ -408,7 +407,9 @@ static void l2tp_ppp_finished(struct ap_session *ses) struct l2tp_sess_t *sess = l2tp_session_self(); log_ppp_debug("l2tp: ppp finished\n"); + __sync_sub_and_fetch(&stat_active, 1); if (sess->state1 != STATE_CLOSE) { + sess->state1 = STATE_CLOSE; l2tp_send_CDN(sess, 2, 0); l2tp_session_free(sess); } else { -- cgit v1.2.3