/* ----------------------------------------------------------------------------- Handle a CCP packet. `rcvd' is 1 if the packet was received, 0 if it is about to be transmitted. mbuf points to the ccp payload (doesn't include FF03 and 80FD) ----------------------------------------------------------------------------- */ void ppp_comp_ccp(struct ppp_if *wan, mbuf_t m, int rcvd) { u_char *p = mbuf_data(m); int slen; slen = CCP_LENGTH(p); if (slen > mbuf_pkthdr_len(m)) { LOGDBG(wan->net, ("ppp_comp_ccp: not enough data in mbuf (expected = %d, got = %d)\n", slen, mbuf_pkthdr_len(m))); return; } switch (CCP_CODE(p)) { case CCP_CONFREQ: case CCP_TERMREQ: case CCP_TERMACK: /* CCP must be going down - disable compression */ wan->sc_flags &= ~(rcvd ? SC_COMP_RUN : SC_DECOMP_RUN); break; case CCP_CONFACK: if (wan->sc_flags & SC_CCP_OPEN && !(wan->sc_flags & SC_CCP_UP) && slen >= CCP_HDRLEN + CCP_OPT_MINLEN && slen >= CCP_OPT_LENGTH(p + CCP_HDRLEN) + CCP_HDRLEN) { if (rcvd) { /* peer is agreeing to send compressed packets. */ if (wan->rc_state && (*wan->rcomp->decomp_init) (wan->rc_state, p + CCP_HDRLEN, slen - CCP_HDRLEN, ifnet_unit(wan->net), 0, wan->mru, ifnet_flags(wan->net) & IFF_DEBUG)) { wan->sc_flags |= SC_DECOMP_RUN; wan->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR); } } else { /* we're agreeing to send compressed packets. */ if (wan->xc_state && (*wan->xcomp->comp_init) (wan->xc_state, p + CCP_HDRLEN, slen - CCP_HDRLEN, ifnet_unit(wan->net), 0, ifnet_mtu(wan->net), ifnet_flags(wan->net) & IFF_DEBUG)) { wan->sc_flags |= SC_COMP_RUN; } } } break; case CCP_RESETACK: if (wan->sc_flags & SC_CCP_UP) { if (rcvd) { if (wan->rc_state && (wan->sc_flags & SC_DECOMP_RUN)) { (*wan->rcomp->decomp_reset)(wan->rc_state); wan->sc_flags &= ~SC_DC_ERROR; } } else { if (wan->xc_state && (wan->sc_flags & SC_COMP_RUN)) (*wan->xcomp->comp_reset)(wan->xc_state); } } break; } }
void handle_ccp(struct pkt *cp, u_char *dp, int len) { int clen; struct compressor **comp; if (len < CCP_HDRLEN) return; clen = CCP_LENGTH(dp); if (clen > len) return; switch (CCP_CODE(dp)) { case CCP_CONFACK: cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP); if (clen < CCP_HDRLEN + CCP_OPT_MINLEN || clen < CCP_HDRLEN + CCP_OPT_LENGTH(dp + CCP_HDRLEN)) break; dp += CCP_HDRLEN; clen -= CCP_HDRLEN; for (comp = compressors; *comp != NULL; ++comp) { if ((*comp)->compress_proto == dp[0]) { if (cp->state != NULL) { (*cp->comp->decomp_free)(cp->state); cp->state = NULL; } cp->comp = *comp; cp->state = (*comp)->decomp_alloc(dp, CCP_OPT_LENGTH(dp)); cp->flags |= CCP_ISUP; if (cp->state != NULL && (*cp->comp->decomp_init) (cp->state, dp, clen, 0, 0, 8192, 1)) cp->flags = (cp->flags & ~CCP_ERR) | CCP_DECOMP_RUN; break; } } break; case CCP_CONFNAK: case CCP_CONFREJ: cp->flags &= ~(CCP_DECOMP_RUN | CCP_ISUP); break; case CCP_RESETACK: if (cp->flags & CCP_ISUP) { if (cp->state && (cp->flags & CCP_DECOMP_RUN)) { (*cp->comp->decomp_reset)(cp->state); cp->flags &= ~CCP_ERROR; } } break; } }