diff options
Diffstat (limited to 'accel-pptpd/ppp_fsm.c')
-rw-r--r-- | accel-pptpd/ppp_fsm.c | 477 |
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; +} |