diff options
author | Guillaume Nault <g.nault@alphalink.fr> | 2012-09-07 12:34:26 +0200 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-09-07 14:48:48 +0400 |
commit | eff719a6d3fd9005a7ee551a0ae53cfa69644de4 (patch) | |
tree | 43f8791c031f78b1ddf07a081c1de4ded571b958 | |
parent | 24d4a04aa76c87898f9d0b16ad43fc8d667432ae (diff) | |
download | accel-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.c | 44 |
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; |