* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define RCSID "$Id: ccp.c,v 1.42 2002/12/23 23:24:37 fcusack Exp $"
+#define RCSID "$Id: ccp.c,v 1.46 2003/05/01 12:30:28 paulus Exp $"
#include <stdlib.h>
#include <string.h>
p[1] = CILEN_DEFLATE;
p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
p[3] = DEFLATE_CHK_SEQUENCE;
- for (;;) {
- if (go->deflate_size < DEFLATE_MIN_WORKS) {
- go->deflate = 0;
- break;
- }
- res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
- if (res > 0) {
- p += CILEN_DEFLATE;
- break;
- } else if (res < 0) {
- go->deflate = 0;
- break;
+ if (p != p0) {
+ p += CILEN_DEFLATE;
+ } else {
+ for (;;) {
+ if (go->deflate_size < DEFLATE_MIN_WORKS) {
+ go->deflate = 0;
+ break;
+ }
+ res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
+ if (res > 0) {
+ p += CILEN_DEFLATE;
+ break;
+ } else if (res < 0) {
+ go->deflate = 0;
+ break;
+ }
+ --go->deflate_size;
+ p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
}
- --go->deflate_size;
- p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
}
if (p != p0 && go->deflate_correct && go->deflate_draft) {
p[0] = CI_DEFLATE_DRAFT;
* Fail if we aren't willing to use his suggestion.
*/
MPPE_CI_TO_OPTS(&p[2], try.mppe);
- if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful)
+ if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) {
+ error("Refusing MPPE stateful mode offered by peer");
try.mppe = 0;
- else if ((go->mppe & try.mppe) != try.mppe)
+ } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) {
/* Peer must have set options we didn't request (suggest) */
try.mppe = 0;
+ }
if (!try.mppe) {
error("MPPE required but peer negotiation failed");
len -= CILEN_MPPE;
}
#endif
- if (go->deflate && len >= CILEN_DEFLATE
- && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
- && p[1] == CILEN_DEFLATE) {
+ if (go->deflate_correct && len >= CILEN_DEFLATE
+ && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
|| p[3] != DEFLATE_CHK_SEQUENCE)
return 0; /* Rej is bad */
- if (go->deflate_correct)
- try.deflate_correct = 0;
- else
- try.deflate_draft = 0;
+ try.deflate_correct = 0;
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ }
+ if (go->deflate_draft && len >= CILEN_DEFLATE
+ && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) {
+ if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ return 0; /* Rej is bad */
+ try.deflate_draft = 0;
p += CILEN_DEFLATE;
len -= CILEN_DEFLATE;
- if (go->deflate_correct && go->deflate_draft
- && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
- && p[1] == CILEN_DEFLATE) {
- if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
- || p[3] != DEFLATE_CHK_SEQUENCE)
- return 0; /* Rej is bad */
- try.deflate_draft = 0;
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- }
- if (!try.deflate_correct && !try.deflate_draft)
- try.deflate = 0;
}
+ if (!try.deflate_correct && !try.deflate_draft)
+ try.deflate = 0;
if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
&& p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
ccp_options *ho = &ccp_hisoptions[f->unit];
ccp_options *ao = &ccp_allowoptions[f->unit];
#ifdef MPPE
- bool seen_ci_mppe = 0;
+ bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
+ /* CI_MPPE, or due to other options? */
#endif
ret = CONFACK;
newret = CONFREJ;
break;
}
- seen_ci_mppe = 1;
MPPE_CI_TO_OPTS(&p[2], ho->mppe);
/* Nak if anything unsupported or unknown are set. */
/* Check state opt */
if (ho->mppe & MPPE_OPT_STATEFUL) {
+ /*
+ * We can Nak and request stateless, but it's a
+ * lot easier to just assume the peer will request
+ * it if he can do it; stateful mode is bad over
+ * the Internet -- which is where we expect MPPE.
+ */
if (refuse_mppe_stateful) {
- /*
- * We can Nak and request stateless, but it's a
- * lot easier to just assume the peer will request
- * it if he can do it; stateful mode is bad over
- * the Internet -- which is where we expect MPPE.
- */
+ error("Refusing MPPE stateful mode offered by peer");
newret = CONFREJ;
break;
- } else {
- newret = CONFNAK;
}
}
newret = CONFREJ;
}
+ /*
+ * We have accepted MPPE or are willing to negotiate
+ * MPPE parameters. A CONFREJ is due to subsequent
+ * (non-MPPE) processing.
+ */
+ rej_for_ci_mppe = 0;
break;
#endif /* MPPE */
case CI_DEFLATE:
*lenp = retp - p0;
}
#ifdef MPPE
- if (ret == CONFREJ && ao->mppe && !seen_ci_mppe) {
+ if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
error("MPPE required but peer negotiation failed");
lcp_close(f->unit, "MPPE required but peer negotiation failed");
}