summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2012-09-07 12:34:26 +0200
committerKozlov Dmitry <xeb@mail.ru>2012-09-07 14:48:48 +0400
commiteff719a6d3fd9005a7ee551a0ae53cfa69644de4 (patch)
tree43f8791c031f78b1ddf07a081c1de4ded571b958
parent24d4a04aa76c87898f9d0b16ad43fc8d667432ae (diff)
downloadaccel-ppp-eff719a6d3fd9005a7ee551a0ae53cfa69644de4.tar.gz
accel-ppp-eff719a6d3fd9005a7ee551a0ae53cfa69644de4.zip
L2TP: Use different states for handling sessions and tunnels
Use the "state" field (struct l2tp_conn_t) for tracking tunnel states and "state1" (struct l2tp_sess_t) for sessions. The meaning of the STATE_* has been slightly modified: * STATE_WAIT_SCCN (tunnel): no modification. * STATE_WAIT_ICRQ (session): now unused. Acceptation of ICRQ messages now depend on the tunnel state (STATE_ESTB). * STATE_WAIT_ICCN (session): no modification. * STATE_ESTB (tunnel and session): for tunnels, means that the tunnel is ready to accept new sessions. For sessions, means that the L2TP session is established, but that it doesn't carry any PPP session yet. * STATE_PPP (session): the session is in use (i.e. it is established and carries a PPP session). * STATE_FIN (tunnel): the tunnel is being closed. * STATE_CLOSE (tunnel and session): default state after allocation/free. For session, this is also the state used once disconnected. Since outgoing calls are not implemented yet, STATE_WAIT_OCRP and STATE_WAIT_OCCN are not used. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
-rw-r--r--accel-pppd/ctrl/l2tp/l2tp.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c
index d436de0e..c4ff01be 100644
--- a/accel-pppd/ctrl/l2tp/l2tp.c
+++ b/accel-pppd/ctrl/l2tp/l2tp.c
@@ -121,13 +121,19 @@ static int l2tp_conn_read(struct triton_md_handler_t *);
static void l2tp_session_free(struct l2tp_conn_t *conn)
{
- if (conn->state == STATE_PPP) {
+ switch (conn->sess.state1) {
+ case STATE_PPP:
__sync_sub_and_fetch(&stat_active, 1);
- conn->state = STATE_FIN;
ap_session_terminate(&conn->sess.ppp.ses,
TERM_USER_REQUEST, 1);
- } else if (conn->state != STATE_FIN)
+ break;
+ case STATE_WAIT_ICCN:
+ case STATE_ESTB:
__sync_sub_and_fetch(&stat_starting, 1);
+ break;
+ default:
+ return;
+ }
if (conn->sess.ppp.fd != -1)
close(conn->sess.ppp.fd);
@@ -140,12 +146,17 @@ static void l2tp_session_free(struct l2tp_conn_t *conn)
_free(conn->sess.ppp.ses.chan_name);
_free(conn->sess.ctrl.calling_station_id);
_free(conn->sess.ctrl.called_station_id);
+
+ conn->sess.state1 = STATE_CLOSE;
}
static void l2tp_tunnel_free(struct l2tp_conn_t *conn)
{
struct l2tp_packet_t *pack;
+ if (conn->state == STATE_CLOSE)
+ return;
+
l2tp_session_free(conn);
triton_md_unregister_handler(&conn->hnd);
@@ -178,6 +189,8 @@ static void l2tp_tunnel_free(struct l2tp_conn_t *conn)
if (conn->challenge_len)
_free(conn->challenge.octets);
+ conn->state = STATE_CLOSE;
+
mempool_free(conn);
}
@@ -229,7 +242,7 @@ static void l2tp_ppp_finished(struct ap_session *ses)
log_ppp_debug("l2tp: ppp finished\n");
- if (conn->state != STATE_FIN) {
+ if (conn->sess.state1 == STATE_PPP) {
__sync_sub_and_fetch(&stat_active, 1);
if (l2tp_terminate(conn, 0, 0))
triton_context_call(&conn->ctx, (triton_event_func)l2tp_tunnel_free, conn);
@@ -272,10 +285,9 @@ static int l2tp_session_alloc(struct l2tp_conn_t *conn)
static void l2tp_conn_close(struct triton_context_t *ctx)
{
struct l2tp_conn_t *conn = container_of(ctx, typeof(*conn), ctx);
-
- if (conn->state == STATE_PPP) {
+
+ if (conn->sess.state1 == STATE_PPP) {
__sync_sub_and_fetch(&stat_active, 1);
- conn->state = STATE_FIN;
ap_session_terminate(&conn->sess.ppp.ses, TERM_ADMIN_RESET, 1);
}
@@ -459,7 +471,7 @@ static int l2tp_session_connect(struct l2tp_conn_t *conn)
__sync_sub_and_fetch(&stat_starting, 1);
__sync_add_and_fetch(&stat_active, 1);
- conn->state = STATE_PPP;
+ conn->sess.state1 = STATE_PPP;
return 0;
@@ -816,7 +828,6 @@ static int l2tp_recv_SCCCN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
return -1;
}
conn->state = STATE_ESTB;
- conn->sess.state1 = STATE_WAIT_ICRQ;
}
else
log_ppp_warn("l2tp: unexpected SCCCN\n");
@@ -843,11 +854,16 @@ static int l2tp_recv_ICRQ(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
struct l2tp_attr_t *attr;
struct l2tp_attr_t *assigned_sid = NULL;
- if (conn->sess.state1 != STATE_WAIT_ICRQ) {
+ if (conn->state != STATE_ESTB) {
log_ppp_warn("l2tp: unexpected ICRQ\n");
return 0;
}
+ if (conn->sess.state1 != STATE_CLOSE) {
+ log_ppp_warn("l2tp: no more session available\n");
+ return 0;
+ }
+
list_for_each_entry(attr, &pack->attrs, entry) {
switch(attr->attr->id) {
case Assigned_Session_ID:
@@ -946,13 +962,7 @@ static int l2tp_recv_CDN(struct l2tp_conn_t *conn, struct l2tp_packet_t *pack)
return 0;
}
- if (conn->state == STATE_PPP) {
- __sync_sub_and_fetch(&stat_active, 1);
- conn->state = STATE_FIN;
- ap_session_terminate(&conn->sess.ppp.ses,
- TERM_USER_REQUEST, 1);
- }
-
+ l2tp_session_free(conn);
if (l2tp_terminate(conn, 0, 0))
return -1;