summaryrefslogtreecommitdiff
path: root/accel-pptpd/ppp_fsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ppp_fsm.c')
-rw-r--r--accel-pptpd/ppp_fsm.c477
1 files changed, 477 insertions, 0 deletions
diff --git a/accel-pptpd/ppp_fsm.c b/accel-pptpd/ppp_fsm.c
new file mode 100644
index 00000000..f966cd07
--- /dev/null
+++ b/accel-pptpd/ppp_fsm.c
@@ -0,0 +1,477 @@
+/*
+* C Implementation: ppp_fsm
+*
+* Description:
+*
+*
+* Author: <xeb@mail.ru>, (C) 2009
+*
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+
+#include "triton/triton.h"
+#include "ppp.h"
+#include "ppp_fsm.h"
+
+void send_term_req(struct ppp_layer_t *layer);
+void send_term_ack(struct ppp_layer_t *layer);
+void send_echo_reply(struct ppp_layer_t *layer);
+
+static void init_req_counter(struct ppp_layer_t *layer,int timeout);
+static void zero_req_counter(struct ppp_layer_t *layer);
+static int restart_timer_func(struct triton_timer_t*t);
+
+void ppp_fsm_init(struct ppp_layer_t *layer)
+{
+ layer->fsm_state=FSM_Initial;
+ layer->restart_timer.active=0;
+ layer->restart_timer.pd=layer;
+ layer->restart_timer.expire=restart_timer_func;
+ layer->restart_timer.period=3000;
+ layer->restart_counter=0;
+ layer->max_terminate=2;
+ layer->max_configure=10;
+ layer->max_failure=5;
+ layer->seq=0;
+}
+
+void ppp_fsm_lower_up(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Initial:
+ layer->fsm_state=FSM_Closed;
+ break;
+ case FSM_Starting:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_lower_down(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closed:
+ case FSM_Closing:
+ layer->fsm_state=FSM_Initial;
+ break;
+ case FSM_Stopped:
+ if (layer->layer_started) layer->layer_started(layer);
+ layer->fsm_state=FSM_Starting;
+ break;
+ case FSM_Stopping:
+ case FSM_Req_Sent:
+ case FSM_Ack_Rcvd:
+ case FSM_Ack_Sent:
+ layer->fsm_state=FSM_Starting;
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ layer->fsm_state=FSM_Starting;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_open(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Initial:
+ if (layer->layer_started) layer->layer_started(layer);
+ layer->fsm_state=FSM_Starting;
+ break;
+ case FSM_Starting:
+ break;
+ case FSM_Closed:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ case FSM_Closing:
+ case FSM_Stopping:
+ layer->fsm_state=FSM_Stopping;
+ case FSM_Stopped:
+ case FSM_Opened:
+ if (layer->opt_restart)
+ {
+ ppp_fsm_lower_down(layer);
+ ppp_fsm_lower_up(layer);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_close(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Starting:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Initial;
+ break;
+ case FSM_Stopped:
+ layer->fsm_state=FSM_Closed;
+ break;
+ case FSM_Stopping:
+ layer->fsm_state=FSM_Closing;
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ case FSM_Req_Sent:
+ case FSM_Ack_Rcvd:
+ case FSM_Ack_Sent:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_terminate);
+ send_term_req(layer);
+ layer->fsm_state=FSM_Closing;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_timeout0(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closing:
+ case FSM_Stopping:
+ send_term_req(layer);
+ break;
+ case FSM_Ack_Rcvd:
+ layer->fsm_state=FSM_Req_Sent;
+ case FSM_Req_Sent:
+ case FSM_Ack_Sent:
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_timeout1(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closing:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Closed;
+ break;
+ case FSM_Stopping:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Stopped;
+ break;
+ case FSM_Ack_Rcvd:
+ case FSM_Req_Sent:
+ case FSM_Ack_Sent:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Stopped;
+ layer->opt_passive=1;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_conf_req_good(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closed:
+ send_term_ack(layer);
+ break;
+ case FSM_Stopped:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ case FSM_Req_Sent:
+ case FSM_Ack_Sent:
+ if (layer->send_conf_ack) layer->send_conf_ack(layer);
+ layer->fsm_state=FSM_Ack_Sent;
+ break;
+ case FSM_Ack_Rcvd:
+ if (layer->send_conf_ack) layer->send_conf_ack(layer);
+ //tlu
+ if (layer->layer_up) layer->layer_up(layer);
+ layer->fsm_state=FSM_Opened;
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ if (layer->send_conf_ack) layer->send_conf_ack(layer);
+ layer->fsm_state=FSM_Ack_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_conf_req_bad(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closed:
+ send_term_ack(layer);
+ break;
+ case FSM_Stopped:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ case FSM_Ack_Sent:
+ if (layer->send_conf_rej) layer->send_conf_rej(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ case FSM_Req_Sent:
+ case FSM_Ack_Rcvd:
+ if (layer->send_conf_rej) layer->send_conf_rej(layer);
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ if (layer->send_conf_rej) layer->send_conf_rej(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_conf_ack(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closed:
+ case FSM_Stopped:
+ send_term_ack(layer);
+ break;
+ case FSM_Req_Sent:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ layer->fsm_state=FSM_Ack_Rcvd;
+ break;
+ case FSM_Ack_Rcvd:
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ case FSM_Ack_Sent:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ //tlu
+ if (layer->layer_up) layer->layer_up(layer);
+ layer->fsm_state=FSM_Opened;
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_conf_rej(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closed:
+ case FSM_Stopped:
+ send_term_ack(layer);
+ break;
+ case FSM_Req_Sent:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_failure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ break;
+ case FSM_Ack_Rcvd:
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ case FSM_Ack_Sent:
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_term_req(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ send_term_req(layer);
+ //if (layer->zero_req_cnt) layer->zero_req_cnt(layer);
+ zero_req_counter(layer);
+ layer->fsm_state=FSM_Stopping;
+ break;
+ case FSM_Req_Sent:
+ case FSM_Ack_Rcvd:
+ case FSM_Ack_Sent:
+ send_term_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ send_term_req(layer);
+ break;
+ }
+}
+
+void ppp_fsm_recv_term_ack(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Closing:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Closed;
+ break;
+ case FSM_Stopping:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Stopped;
+ break;
+ case FSM_Ack_Rcvd:
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_unk(struct ppp_layer_t *layer)
+{
+ if (layer->send_conf_rej) layer->send_conf_rej(layer);
+}
+
+void ppp_fsm_recv_code_rej_perm(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Ack_Rcvd:
+ layer->fsm_state=FSM_Req_Sent;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_code_rej_bad(struct ppp_layer_t *layer)
+{
+ switch(layer->fsm_state)
+ {
+ case FSM_Opened:
+ if (layer->layer_down) layer->layer_down(layer);
+ //if (layer->init_req_cnt) layer->init_req_cnt(layer);
+ init_req_counter(layer,layer->max_configure);
+ if (layer->send_conf_req) layer->send_conf_req(layer);
+ layer->fsm_state=FSM_Stopping;
+ break;
+ case FSM_Closing:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Closed;
+ break;
+ case FSM_Stopping:
+ case FSM_Req_Sent:
+ case FSM_Ack_Rcvd:
+ case FSM_Ack_Sent:
+ if (layer->layer_finished) layer->layer_finished(layer);
+ layer->fsm_state=FSM_Stopped;
+ break;
+ default:
+ break;
+ }
+}
+
+void ppp_fsm_recv_echo(struct ppp_layer_t *layer)
+{
+ if (layer->fsm_state==FSM_Opened)
+ send_echo_reply(layer);
+}
+
+void send_term_req(struct ppp_layer_t *layer)
+{
+ struct ppp_hdr_t hdr={
+ .code=TERMREQ,
+ .id=++layer->seq,
+ .len=4,
+ };
+
+ ppp_send(layer->ppp,&hdr,hdr.len);
+}
+void send_term_ack(struct ppp_layer_t *layer)
+{
+ struct ppp_hdr_t hdr={
+ .code=TERMACK,
+ .id=layer->recv_id,
+ .len=4,
+ };
+
+ ppp_send(layer->ppp,&hdr,hdr.len);
+}
+void send_echo_reply(struct ppp_layer_t *layer)
+{
+ struct ppp_hdr_t hdr={
+ .code=ECHOREP,
+ .id=layer->recv_id,
+ .len=8,
+ };
+
+ *(int*)hdr.data=layer->magic_num;
+
+ ppp_send(layer->ppp,&hdr,hdr.len);
+}
+
+void ppp_fsm_recv(struct ppp_layer_t *layer)
+{
+}
+
+static void init_req_counter(struct ppp_layer_t *layer,int timeout)
+{
+ triton_timer_del(&layer->restart_timer);
+ triton_timer_add(&layer->restart_timer);
+ layer->restart_counter=timeout;
+}
+static void zero_req_counter(struct ppp_layer_t *layer)
+{
+ triton_timer_del(&layer->restart_timer);
+ triton_timer_add(&layer->restart_timer);
+ layer->restart_counter=0;
+}
+
+static int restart_timer_func(struct triton_timer_t*t)
+{
+ struct ppp_layer_t *layer=(struct ppp_layer_t *)t->pd;
+
+ if (layer->restart_counter)
+ {
+ ppp_fsm_timeout0(layer);
+ layer->restart_counter--;
+ return 1;
+ }
+
+ ppp_fsm_timeout1(layer);
+ return 0;
+}