summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/ppp_ipcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/ppp/ppp_ipcp.c')
-rw-r--r--accel-pppd/ppp/ppp_ipcp.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c
index 5d66c9d..bd9f50d 100644
--- a/accel-pppd/ppp/ppp_ipcp.c
+++ b/accel-pppd/ppp/ppp_ipcp.c
@@ -23,6 +23,7 @@ struct recv_opt_t
};
static LIST_HEAD(option_handlers);
+static struct ppp_layer_t ipcp_layer;
static void ipcp_layer_up(struct ppp_fsm_t*);
static void ipcp_layer_down(struct ppp_fsm_t*);
@@ -134,10 +135,8 @@ void ipcp_layer_free(struct ppp_layer_data_t *ld)
_free(ipcp);
}
-static void ipcp_layer_up(struct ppp_fsm_t *fsm)
+static void __ipcp_layer_up(struct ppp_ipcp_t *ipcp)
{
- struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm);
-
log_ppp_debug("ipcp_layer_started\n");
if (!ipcp->started) {
@@ -146,6 +145,14 @@ static void ipcp_layer_up(struct ppp_fsm_t *fsm)
}
}
+static void ipcp_layer_up(struct ppp_fsm_t *fsm)
+{
+ struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm);
+
+ if (!ipcp->delay_ack)
+ __ipcp_layer_up(ipcp);
+}
+
static void ipcp_layer_down(struct ppp_fsm_t *fsm)
{
struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm);
@@ -181,7 +188,7 @@ static int send_conf_req(struct ppp_fsm_t *fsm)
ipcp_hdr->proto = htons(PPP_IPCP);
ipcp_hdr->code = CONFREQ;
- ipcp_hdr->id = ++ipcp->fsm.id;
+ ipcp_hdr->id = ipcp->fsm.id;
ipcp_hdr->len = 0;
ptr += sizeof(*ipcp_hdr);
@@ -221,6 +228,11 @@ static void send_conf_ack(struct ppp_fsm_t *fsm)
struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm);
struct ipcp_hdr_t *hdr = (struct ipcp_hdr_t*)ipcp->ppp->buf;
+ if (ipcp->delay_ack) {
+ send_term_ack(fsm);
+ return;
+ }
+
hdr->code = CONFACK;
if (conf_ppp_verbose)
@@ -409,11 +421,11 @@ static int ipcp_recv_conf_rej(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [IPCP ConfRej id=%x", ipcp->fsm.recv_id);
- if (ipcp->fsm.recv_id != ipcp->fsm.id) {
+ /*if (ipcp->fsm.recv_id != ipcp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ipcp_opt_hdr_t *)data;
@@ -447,11 +459,11 @@ static int ipcp_recv_conf_nak(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [IPCP ConfNak id=%x", ipcp->fsm.recv_id);
- if (ipcp->fsm.recv_id != ipcp->fsm.id) {
+ /*if (ipcp->fsm.recv_id != ipcp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ipcp_opt_hdr_t *)data;
@@ -487,11 +499,11 @@ static int ipcp_recv_conf_ack(struct ppp_ipcp_t *ipcp, uint8_t *data, int size)
if (conf_ppp_verbose)
log_ppp_info2("recv [IPCP ConfAck id=%x", ipcp->fsm.recv_id);
- if (ipcp->fsm.recv_id != ipcp->fsm.id) {
+ /*if (ipcp->fsm.recv_id != ipcp->fsm.id) {
if (conf_ppp_verbose)
log_ppp_info2(": id mismatch ]\n");
return 0;
- }
+ }*/
while (size > 0) {
hdr = (struct ipcp_opt_hdr_t *)data;
@@ -557,6 +569,7 @@ static void ipcp_recv(struct ppp_handler_t*h)
struct ipcp_hdr_t *hdr;
struct ppp_ipcp_t *ipcp = container_of(h, typeof(*ipcp), hnd);
int r;
+ int delay_ack = ipcp->delay_ack;
if (ipcp->fsm.fsm_state == FSM_Initial || ipcp->fsm.fsm_state == FSM_Closed || ipcp->ppp->terminating) {
if (conf_ppp_verbose)
@@ -574,8 +587,12 @@ static void ipcp_recv(struct ppp_handler_t*h)
log_ppp_warn("IPCP: short packet received\n");
return;
}
+
+ if ((hdr->code == CONFACK || hdr->code == CONFNAK || hdr->code == CONFREJ) && hdr->id != ipcp->fsm.id)
+ return;
ipcp->fsm.recv_id = hdr->id;
+
switch(hdr->code) {
case CONFREQ:
r = ipcp_recv_conf_req(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN);
@@ -583,16 +600,25 @@ static void ipcp_recv(struct ppp_handler_t*h)
ipcp_free_conf_req(ipcp);
return;
}
- switch(r) {
- case IPCP_OPT_ACK:
- ppp_fsm_recv_conf_req_ack(&ipcp->fsm);
- break;
- case IPCP_OPT_NAK:
- ppp_fsm_recv_conf_req_nak(&ipcp->fsm);
- break;
- case IPCP_OPT_REJ:
- ppp_fsm_recv_conf_req_rej(&ipcp->fsm);
- break;
+ if (delay_ack && !ipcp->delay_ack)
+ __ipcp_layer_up(ipcp);
+ if (ipcp->started || delay_ack) {
+ if (r == IPCP_OPT_ACK)
+ send_conf_ack(&ipcp->fsm);
+ else
+ r = IPCP_OPT_FAIL;
+ } else {
+ switch(r) {
+ case IPCP_OPT_ACK:
+ ppp_fsm_recv_conf_req_ack(&ipcp->fsm);
+ break;
+ case IPCP_OPT_NAK:
+ ppp_fsm_recv_conf_req_nak(&ipcp->fsm);
+ break;
+ case IPCP_OPT_REJ:
+ ppp_fsm_recv_conf_req_rej(&ipcp->fsm);
+ break;
+ }
}
ipcp_free_conf_req(ipcp);
if (r == IPCP_OPT_FAIL)
@@ -650,6 +676,19 @@ int ipcp_option_register(struct ipcp_option_handler_t *h)
return 0;
}
+struct ipcp_option_t *ipcp_find_option(struct ppp_t *ppp, struct ipcp_option_handler_t *h)
+{
+ struct ppp_ipcp_t *ipcp = container_of(ppp_find_layer_data(ppp, &ipcp_layer), typeof(*ipcp), ld);
+ struct ipcp_option_t *opt;
+
+ list_for_each_entry(opt, &ipcp->options, entry)
+ if (opt->h == h)
+ return opt;
+
+ log_emerg("ipcp: BUG: option not found\n");
+ abort();
+}
+
static struct ppp_layer_t ipcp_layer =
{
.init = ipcp_layer_init,
@@ -658,8 +697,9 @@ static struct ppp_layer_t ipcp_layer =
.free = ipcp_layer_free,
};
-static void __init ipcp_init(void)
+static void ipcp_init(void)
{
ppp_register_layer("ipcp", &ipcp_layer);
}
+DEFINE_INIT(3, ipcp_init);