*/
#ifndef lint
-static char rcsid[] = "$Id: ccp.c,v 1.12 1995/10/27 03:42:52 paulus Exp $";
+static char rcsid[] = "$Id: ccp.c,v 1.16 1996/04/04 03:35:37 paulus Exp $";
#endif
+#include <string.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <net/ppp-comp.h>
#include "fsm.h"
#include "ccp.h"
+struct protent ccp_protent = {
+ PPP_CCP, ccp_init, ccp_input, ccp_protrej,
+ ccp_lowerup, ccp_lowerdown, ccp_open, ccp_close,
+ ccp_printpkt, ccp_datainput, 1, "CCP", NULL, NULL
+};
+
fsm ccp_fsm[NUM_PPP];
ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
- ccp_wantoptions[0].bsd_compress = 1;
- ccp_wantoptions[0].bsd_bits = 12; /* default value */
+ ccp_wantoptions[0].deflate = 1;
+ ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+ ccp_allowoptions[0].deflate = 1;
+ ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+ ccp_wantoptions[0].bsd_compress = 1;
+ ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
ccp_allowoptions[0].bsd_compress = 1;
ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
+
+ ccp_allowoptions[0].predictor_1 = 1;
}
/*
if (f->state != OPENED)
ccp_flags_set(unit, 1, 0);
- if (!ANY_COMPRESS(ccp_wantoptions[unit]))
+
+ /*
+ * Find out which compressors the kernel supports before
+ * deciding whether to open in silent mode.
+ */
+ ccp_resetci(f);
+ if (!ANY_COMPRESS(ccp_gotoptions[unit]))
f->flags |= OPT_SILENT;
+
fsm_open(f);
}
* ccp_close - Terminate CCP.
*/
void
-ccp_close(unit)
+ccp_close(unit, reason)
int unit;
+ char *reason;
{
ccp_flags_set(unit, 0, 0);
- fsm_close(&ccp_fsm[unit]);
+ fsm_close(&ccp_fsm[unit], reason);
}
/*
*/
if (oldstate == REQSENT && p[0] == TERMACK
&& !ANY_COMPRESS(ccp_gotoptions[unit]))
- ccp_close(unit);
+ ccp_close(unit, "No compression negotiated");
}
/*
ccp_resetci(f)
fsm *f;
{
- int ok;
ccp_options *go = &ccp_gotoptions[f->unit];
u_char opt_buf[16];
if (len < CILEN_PREDICTOR_1
|| p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
return 0;
+ p += CILEN_PREDICTOR_1;
+ len -= CILEN_PREDICTOR_1;
/* XXX Cope with first/fast ack */
if (p == p0 && len == 0)
return 1;
if (len < CILEN_PREDICTOR_2
|| p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
return 0;
+ p += CILEN_PREDICTOR_2;
+ len -= CILEN_PREDICTOR_2;
/* XXX Cope with first/fast ack */
if (p == p0 && len == 0)
return 1;
ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
|| p[3] != DEFLATE_CHK_SEQUENCE
- || nb > ao->deflate_size) {
+ || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
newret = CONFNAK;
- nb = ao->deflate_size;
- } else {
- /*
- * Check whether we can do Deflate with the window
- * size they want. If the window is too big, reduce
- * it until the kernel can cope and nak with that.
- */
+ if (!dont_nak) {
+ p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
+ p[3] = DEFLATE_CHK_SEQUENCE;
+ }
+ break;
+ }
+
+ /*
+ * Check whether we can do Deflate with the window
+ * size they want. If the window is too big, reduce
+ * it until the kernel can cope and nak with that.
+ * We only check this for the first option.
+ */
+ if (p == p0) {
for (;;) {
- if (nb < DEFLATE_MIN_SIZE) {
+ res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
+ if (res > 0)
+ break; /* it's OK now */
+ if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
newret = CONFREJ;
p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
break;
}
- p[2] = DEFLATE_MAKE_OPT(nb);
- res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
- if (res != 0) {
- if (res < 0)
- newret = CONFREJ;
- break;
- }
newret = CONFNAK;
--nb;
- }
- }
- if (newret == CONFNAK && !dont_nak) {
- if (nb >= DEFLATE_MIN_SIZE) {
p[2] = DEFLATE_MAKE_OPT(nb);
- p[3] = DEFLATE_CHK_SEQUENCE;
- } else {
- newret = CONFREJ;
}
}
break;
ho->bsd_compress = 1;
ho->bsd_bits = nb = BSD_NBITS(p[2]);
if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
- || nb > ao->bsd_bits) {
+ || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
newret = CONFNAK;
- nb = ao->bsd_bits;
- } else {
- /*
- * Check whether we can do BSD_Compress with the code
- * size they want. If the code size is too big, reduce
- * it until the kernel can cope and nak with that.
- */
+ if (!dont_nak)
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
+ break;
+ }
+
+ /*
+ * Check whether we can do BSD-Compress with the code
+ * size they want. If the code size is too big, reduce
+ * it until the kernel can cope and nak with that.
+ * We only check this for the first option.
+ */
+ if (p == p0) {
for (;;) {
- if (nb < BSD_MIN_BITS) {
+ res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
+ if (res > 0)
+ break;
+ if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
newret = CONFREJ;
p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
ho->bsd_bits);
break;
}
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
- res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
- if (res != 0) {
- if (res < 0)
- newret = CONFREJ;
- break;
- }
newret = CONFNAK;
--nb;
- }
- }
- if (newret == CONFNAK && !dont_nak) {
- if (nb >= BSD_MIN_BITS) {
p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
- } else {
- newret = CONFREJ;
}
}
break;
}
ho->predictor_1 = 1;
- if (ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
+ if (p == p0
+ && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
newret = CONFREJ;
}
break;
}
ho->predictor_2 = 1;
- if (ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
+ if (p == p0
+ && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
newret = CONFREJ;
}
break;
* Disable compression by taking CCP down.
*/
syslog(LOG_ERR, "Lost compression sync: disabling compression");
- ccp_close(unit);
+ ccp_close(unit, "Lost compression sync");
} else {
/*
* Send a reset-request to reset the peer's compressor.