diff --git a/src/netif/ppp/mppe.c b/src/netif/ppp/mppe.c index 907c820c..1996f809 100644 --- a/src/netif/ppp/mppe.c +++ b/src/netif/ppp/mppe.c @@ -198,20 +198,31 @@ void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) { - struct pbuf *n; + struct pbuf *n, *np; u8_t *pl; + err_t err; - if (pbuf_header(*pb, (s16_t)(MPPE_OVHD + sizeof(protocol))) == 0) { - pbuf_ref(*pb); - } else { - struct pbuf *np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol), PBUF_RAM); - if (!np) { - return ERR_MEM; - } - pbuf_chain(np, *pb); - *pb = np; + /* TCP stack requires that we don't change the packet payload, therefore we copy + * the whole packet before encryption. + */ + np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); + if (!np) { + return ERR_MEM; } - pl = (u8_t*)(*pb)->payload; + + /* Hide MPPE header + protocol */ + pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); + + if ((err = pbuf_copy(np, *pb)) != ERR_OK) { + pbuf_free(np); + return err; + } + + /* Reveal MPPE header + protocol */ + pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); + + *pb = np; + pl = (u8_t*)np->payload; state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); @@ -239,10 +250,10 @@ mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t proto pl[1] = protocol; /* Hide MPPE header */ - pbuf_header(*pb, -(s16_t)MPPE_OVHD); + pbuf_header(np, -(s16_t)MPPE_OVHD); /* Encrypt packet */ - for (n = *pb; n != NULL; n = n->next) { + for (n = np; n != NULL; n = n->next) { arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); if (n->tot_len == n->len) { break; @@ -250,7 +261,7 @@ mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t proto } /* Reveal MPPE header */ - pbuf_header(*pb, (s16_t)MPPE_OVHD); + pbuf_header(np, (s16_t)MPPE_OVHD); return ERR_OK; }