summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/ppp_ccp.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/ppp/ppp_ccp.c')
-rw-r--r--accel-pppd/ppp/ppp_ccp.c172
1 files changed, 109 insertions, 63 deletions
diff --git a/accel-pppd/ppp/ppp_ccp.c b/accel-pppd/ppp/ppp_ccp.c
index 58a4abf6..79b0c32d 100644
--- a/accel-pppd/ppp/ppp_ccp.c
+++ b/accel-pppd/ppp/ppp_ccp.c
@@ -26,12 +26,14 @@ struct recv_opt_t
};
static int conf_ccp = 1;
+static int conf_ccp_max_configure = 3;
static struct ppp_layer_t ccp_layer;
static LIST_HEAD(option_handlers);
static void ccp_layer_up(struct ppp_fsm_t*);
static void ccp_layer_down(struct ppp_fsm_t*);
+static void ccp_layer_finished(struct ppp_fsm_t*);
static int send_conf_req(struct ppp_fsm_t*);
static void send_conf_ack(struct ppp_fsm_t*);
static void send_conf_nak(struct ppp_fsm_t*);
@@ -105,16 +107,19 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp)
ppp_register_unit_handler(ppp, &ccp->hnd);
+ ccp->passive = 1;
+
INIT_LIST_HEAD(&ccp->options);
ccp_options_init(ccp);
-
- ccp->passive = 0;
ccp->fsm.proto = PPP_CCP;
ppp_fsm_init(&ccp->fsm);
+ ccp->fsm.max_configure = conf_ccp_max_configure;
+
ccp->fsm.layer_up = ccp_layer_up;
- ccp->fsm.layer_finished = ccp_layer_down;
+ ccp->fsm.layer_finished = ccp_layer_finished;
+ ccp->fsm.layer_down = ccp_layer_down;
ccp->fsm.send_conf_req = send_conf_req;
ccp->fsm.send_conf_ack = send_conf_ack;
ccp->fsm.send_conf_nak = send_conf_nak;
@@ -134,13 +139,18 @@ int ccp_layer_start(struct ppp_layer_data_t *ld)
log_ppp_debug("ccp_layer_start\n");
if (list_empty(&ccp->options) || !conf_ccp) {
+ ccp->started = 1;
ppp_layer_started(ccp->ppp, &ccp->ld);
return 0;
}
-
- ppp_fsm_lower_up(&ccp->fsm);
- if (ppp_fsm_open(&ccp->fsm))
- return -1;
+
+ ccp->starting = 1;
+
+ if (!ccp->passive) {
+ ppp_fsm_lower_up(&ccp->fsm);
+ if (ppp_fsm_open(&ccp->fsm))
+ return -1;
+ }
if (ccp_set_flags(ccp->ppp->unit_fd, 1, 0)) {
ppp_fsm_close(&ccp->fsm);
@@ -159,7 +169,7 @@ void ccp_layer_finish(struct ppp_layer_data_t *ld)
ccp_set_flags(ccp->ppp->unit_fd, 0, 0);
ccp->fsm.fsm_state = FSM_Closed;
-
+
log_ppp_debug("ccp_layer_finished\n");
ppp_layer_finished(ccp->ppp, &ccp->ld);
}
@@ -181,9 +191,8 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm)
{
struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
- log_ppp_debug("ccp_layer_started\n");
-
if (!ccp->started) {
+ log_ppp_debug("ccp_layer_started\n");
ccp->started = 1;
if (ccp_set_flags(ccp->ppp->unit_fd, 1, 1)) {
ppp_terminate(ccp->ppp, TERM_NAS_ERROR, 0);
@@ -193,18 +202,28 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm)
}
}
-static void ccp_layer_down(struct ppp_fsm_t *fsm)
+static void ccp_layer_finished(struct ppp_fsm_t *fsm)
{
struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
log_ppp_debug("ccp_layer_finished\n");
- if (!ccp->started)
+ if (!ccp->started) {
+ ccp->started = 1;
ppp_layer_started(ccp->ppp, &ccp->ld);
- ccp->started = 0;
- ppp_layer_finished(ccp->ppp, &ccp->ld);
+ }
}
+static void ccp_layer_down(struct ppp_fsm_t *fsm)
+{
+ struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
+
+ log_ppp_debug("ccp_layer_down\n");
+
+ ppp_fsm_close(fsm);
+}
+
+
static void print_ropt(struct recv_opt_t *ropt)
{
int i;
@@ -225,19 +244,15 @@ static int send_conf_req(struct ppp_fsm_t *fsm)
struct ccp_option_t *lopt;
int n;
- ccp->need_req = 0;
-
- if (ccp->passive) {
- ccp->passive--;
+ if (ccp->passive)
return 0;
- }
buf = _malloc(ccp->conf_req_len);
ccp_hdr = (struct ccp_hdr_t*)buf;
ccp_hdr->proto = htons(PPP_CCP);
ccp_hdr->code = CONFREQ;
- ccp_hdr->id = ++ccp->fsm.id;
+ ccp_hdr->id = ccp->fsm.id;
ccp_hdr->len = 0;
ptr = (uint8_t*)(ccp_hdr + 1);
@@ -287,7 +302,7 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm);
uint8_t *buf = _malloc(ccp->conf_req_len), *ptr = buf;
struct ccp_hdr_t *ccp_hdr = (struct ccp_hdr_t*)ptr;
- struct recv_opt_t *ropt;
+ struct ccp_option_t *lopt;
if (conf_ppp_verbose)
log_ppp_info2("send [CCP ConfNak id=%x", ccp->fsm.recv_id);
@@ -299,13 +314,13 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
ptr += sizeof(*ccp_hdr);
- list_for_each_entry(ropt, &ccp->ropt_list, entry) {
- if (ropt->state == CCP_OPT_NAK) {
+ list_for_each_entry(lopt, &ccp->options, entry) {
+ if (lopt->state == CCP_OPT_NAK) {
if (conf_ppp_verbose) {
log_ppp_info2(" ");
- ropt->lopt->h->print(log_ppp_info2, ropt->lopt, NULL);
+ lopt->h->print(log_ppp_info2, lopt, NULL);
}
- ptr += ropt->lopt->h->send_conf_nak(ccp, ropt->lopt, ptr);
+ ptr += lopt->h->send_conf_nak(ccp, lopt, ptr);
}
}
@@ -365,7 +380,6 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size)
struct ccp_option_t *lopt;
int r, ret = 1, ack = 0;
- ccp->need_req = 0;
ccp->ropt_len = size;
while (size > 0) {
@@ -402,8 +416,6 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size)
lopt->state = CCP_OPT_REJ;
ropt->state = CCP_OPT_REJ;
} else {
- /*if (lopt->state == CCP_OPT_NAK && r == CCP_OPT_ACK)
- ccp->need_req = 1;*/
lopt->state = r;
ropt->state = r;
}
@@ -428,15 +440,14 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("]\n");
- /*list_for_each_entry(lopt,&ccp->options,entry)
- {
- if (lopt->state==CCP_OPT_NONE)
- {
- r=lopt->h->recv_conf_req(ccp,lopt,NULL);
- lopt->state=r;
- if (r<ret) ret=r;
+ list_for_each_entry(lopt, &ccp->options, entry) {
+ if (lopt->state == CCP_OPT_NONE) {
+ r = lopt->h->recv_conf_req(ccp, lopt, NULL);
+ lopt->state = r;
+ if (r < ret)
+ ret = r;
}
- }*/
+ }
return ret;
}
@@ -461,11 +472,11 @@ static int ccp_recv_conf_rej(struct ppp_ccp_t *ccp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [CCP ConfRej id=%x", ccp->fsm.recv_id);
- if (ccp->fsm.recv_id != ccp->fsm.id) {
+ /*if (ccp->fsm.recv_id != ccp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ccp_opt_hdr_t *)data;
@@ -499,11 +510,11 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [CCP ConfNak id=%x", ccp->fsm.recv_id);
- if (ccp->fsm.recv_id != ccp->fsm.id) {
+ /*if (ccp->fsm.recv_id != ccp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ccp_opt_hdr_t *)data;
@@ -516,8 +527,6 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size)
}
if (lopt->h->recv_conf_nak && lopt->h->recv_conf_nak(ccp, lopt, data))
res = -1;
- //lopt->state = CCP_OPT_NAK;
- //ccp->need_req = 1;
break;
}
}
@@ -541,11 +550,11 @@ static int ccp_recv_conf_ack(struct ppp_ccp_t *ccp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [CCP ConfAck id=%x", ccp->fsm.recv_id);
- if (ccp->fsm.recv_id != ccp->fsm.id) {
+ /*if (ccp->fsm.recv_id != ccp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ccp_opt_hdr_t *)data;
@@ -612,7 +621,7 @@ static void ccp_recv(struct ppp_handler_t*h)
struct ppp_ccp_t *ccp = container_of(h, typeof(*ccp), hnd);
int r;
- if (ccp->fsm.fsm_state == FSM_Initial || ccp->fsm.fsm_state == FSM_Closed || ccp->ppp->terminating) {
+ if (!ccp->starting || ccp->fsm.fsm_state == FSM_Closed || ccp->ppp->terminating) {
if (conf_ppp_verbose)
log_ppp_warn("CCP: discarding packet\n");
if (ccp->fsm.fsm_state == FSM_Closed || !conf_ccp)
@@ -631,38 +640,51 @@ static void ccp_recv(struct ppp_handler_t*h)
return;
}
+ if ((hdr->code == CONFACK || hdr->code == CONFNAK || hdr->code == CONFREJ) && hdr->id != ccp->fsm.id)
+ return;
+
ccp->fsm.recv_id = hdr->id;
+
switch(hdr->code) {
- case CONFREQ:
+ case CONFREQ:
r = ccp_recv_conf_req(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
- switch(r) {
- case CCP_OPT_ACK:
- ppp_fsm_recv_conf_req_ack(&ccp->fsm);
- break;
- case CCP_OPT_NAK:
- ppp_fsm_recv_conf_req_nak(&ccp->fsm);
- break;
- case CCP_OPT_REJ:
- ppp_fsm_recv_conf_req_rej(&ccp->fsm);
- break;
+ if (ccp->passive) {
+ ccp->passive = 0;
+ ppp_fsm_lower_up(&ccp->fsm);
+ ppp_fsm_open(&ccp->fsm);
+ }
+ if (ccp->started) {
+ if (r == CCP_OPT_ACK)
+ send_conf_ack(&ccp->fsm);
+ else
+ r = CCP_OPT_FAIL;
+ } else {
+ switch(r) {
+ case CCP_OPT_ACK:
+ ppp_fsm_recv_conf_req_ack(&ccp->fsm);
+ break;
+ case CCP_OPT_NAK:
+ ppp_fsm_recv_conf_req_nak(&ccp->fsm);
+ break;
+ case CCP_OPT_REJ:
+ ppp_fsm_recv_conf_req_rej(&ccp->fsm);
+ break;
+ }
}
ccp_free_conf_req(ccp);
- if (r == CCP_OPT_ACK && ccp->passive) {
+ /*if (r == CCP_OPT_ACK && ccp->passive) {
ccp->passive = 0;
send_conf_req(&ccp->fsm);
- }
+ }*/
if (r == CCP_OPT_FAIL)
ppp_terminate(ccp->ppp, TERM_USER_ERROR, 0);
break;
case CONFACK:
if (ccp_recv_conf_ack(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN))
ppp_terminate(ccp->ppp, TERM_USER_ERROR, 0);
- else {
+ else
ppp_fsm_recv_conf_ack(&ccp->fsm);
- if (ccp->need_req)
- send_conf_req(&ccp->fsm);
- }
break;
case CONFNAK:
ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
@@ -720,6 +742,10 @@ int ccp_option_register(struct ccp_option_handler_t *h)
return 0;
}
+struct ppp_ccp_t *ccp_find_layer_data(struct ppp_t *ppp)
+{
+ return container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(struct ppp_ccp_t), ld);
+}
struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h)
{
struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld);
@@ -733,6 +759,21 @@ struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handle
abort();
}
+int ccp_ipcp_started(struct ppp_t *ppp)
+{
+ struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld);
+
+ if (ccp->passive) {
+ ccp->fsm.fsm_state = FSM_Closed;
+ ccp->started = 1;
+ ppp_layer_started(ccp->ppp, &ccp->ld);
+
+ return 0;
+ }
+
+ return !ccp->started;
+}
+
static struct ppp_layer_t ccp_layer=
{
.init = ccp_layer_init,
@@ -748,9 +789,13 @@ static void load_config(void)
opt = conf_get_opt("ppp", "ccp");
if (opt && atoi(opt) >= 0)
conf_ccp = atoi(opt);
+
+ opt = conf_get_opt("ppp", "ccp-max-configure");
+ if (opt && atoi(opt) > 0)
+ conf_ccp_max_configure = atoi(opt);
}
-static void __init ccp_init(void)
+static void ccp_init(void)
{
ppp_register_layer("ccp", &ccp_layer);
@@ -758,3 +803,4 @@ static void __init ccp_init(void)
triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
}
+DEFINE_INIT(3, ccp_init);