diff options
Diffstat (limited to 'accel-pppd/ppp/ppp_ipcp.c')
-rw-r--r-- | accel-pppd/ppp/ppp_ipcp.c | 82 |
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); |