From 03036ec70d259c58af0bf1c507a71279158f37d6 Mon Sep 17 00:00:00 2001 From: Brian Somers Date: Tue, 17 Mar 1998 22:29:12 +0000 Subject: [PATCH] Make all CCP negotiation data dynamic and add a ``set deflate'' command to configure the DEFLATE default window size. --- usr.sbin/ppp/ccp.c | 182 ++++++++++++++------- usr.sbin/ppp/ccp.h | 58 ++++--- usr.sbin/ppp/command.c | 26 ++- usr.sbin/ppp/command.h | 13 +- usr.sbin/ppp/deflate.c | 349 +++++++++++++++++++---------------------- usr.sbin/ppp/ppp.8 | 16 +- usr.sbin/ppp/pred.c | 143 ++++++++--------- 7 files changed, 441 insertions(+), 346 deletions(-) diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c index c39bdeeade0..e683f8a587f 100644 --- a/usr.sbin/ppp/ccp.c +++ b/usr.sbin/ppp/ccp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ccp.c,v 1.30.2.22 1998/03/16 22:51:49 brian Exp $ + * $Id: ccp.c,v 1.30.2.23 1998/03/16 22:53:31 brian Exp $ * * TODO: * o Support other compression protocols @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -150,6 +151,8 @@ ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, /* Initialise ourselves */ fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, CCP_MAXCODE, 10, LogCCP, bundle, l, parent, &ccp_Callbacks); + ccp->cfg.deflate.in.winsize = 0; + ccp->cfg.deflate.out.winsize = 15; ccp_Setup(ccp); } @@ -161,9 +164,11 @@ ccp_Setup(struct ccp *ccp) ccp->fsm.maxconfig = 10; ccp->his_proto = ccp->my_proto = -1; ccp->reset_sent = ccp->last_reset = -1; - ccp->in_algorithm = ccp->out_algorithm = -1; + ccp->in.algorithm = ccp->out.algorithm = -1; + ccp->in.state = ccp->out.state = NULL; + ccp->in.opt.id = -1; + ccp->out.opt = NULL; ccp->his_reject = ccp->my_reject = 0; - ccp->out_init = ccp->in_init = 0; ccp->uncompout = ccp->compout = 0; ccp->uncompin = ccp->compin = 0; } @@ -181,26 +186,47 @@ CcpSendConfigReq(struct fsm *fp) { /* Send config REQ please */ struct ccp *ccp = fsm2ccp(fp); + struct ccp_opt **o; u_char *cp, buff[100]; - int f; + int f, alloc; LogPrintf(LogCCP, "CcpSendConfigReq\n"); cp = buff; + o = &ccp->out.opt; + alloc = ccp->his_reject == 0 && ccp->out.opt == NULL; ccp->my_proto = -1; - ccp->out_algorithm = -1; + ccp->out.algorithm = -1; for (f = 0; f < NALGORITHMS; f++) if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) { - struct lcp_opt o; + if (alloc) { + *o = (struct ccp_opt *)malloc(sizeof(struct ccp_opt)); + (*o)->val.id = algorithm[f]->id; + (*o)->val.len = 2; + (*o)->next = NULL; + (*o)->algorithm = f; + (*algorithm[f]->o.OptInit)(&(*o)->val, &ccp->cfg); + } else { + for (o = &ccp->out.opt; *o != NULL; o = &(*o)->next) + if ((*o)->val.id == algorithm[f]->id && (*o)->algorithm == f) + break; + if (*o == NULL) { + LogPrintf(LogERROR, "CCP REQ buffer lost !\n"); + break; + } + } - (*algorithm[f]->o.Get)(&o); - if (cp + o.len > buff + sizeof buff) { + if (cp + (*o)->val.len > buff + sizeof buff) { LogPrintf(LogERROR, "CCP REQ buffer overrun !\n"); break; } - cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id], - (*algorithm[f]->Disp)(&o)); - ccp->my_proto = o.id; - ccp->out_algorithm = f; + cp += LcpPutConf(LogCCP, cp, &(*o)->val, cftypes[(*o)->val.id], + (*algorithm[f]->Disp)(&(*o)->val)); + + ccp->my_proto = (*o)->val.id; + ccp->out.algorithm = f; + + if (alloc) + o = &(*o)->next; } FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, buff, cp - buff); } @@ -235,8 +261,8 @@ CcpRecvResetReq(struct fsm *fp) { /* Got a reset REQ, reset outgoing dictionary */ struct ccp *ccp = fsm2ccp(fp); - if (ccp->out_init) - (*algorithm[ccp->out_algorithm]->o.Reset)(); + if (ccp->out.state != NULL) + (*algorithm[ccp->out.algorithm]->o.Reset)(ccp->out.state); } static void @@ -252,13 +278,13 @@ CcpLayerFinish(struct fsm *fp) /* We're now down */ struct ccp *ccp = fsm2ccp(fp); LogPrintf(LogCCP, "CcpLayerFinish.\n"); - if (ccp->in_init) { - (*algorithm[ccp->in_algorithm]->i.Term)(); - ccp->in_init = 0; + if (ccp->in.state != NULL) { + (*algorithm[ccp->in.algorithm]->i.Term)(ccp->in.state); + ccp->in.state = NULL; } - if (ccp->out_init) { - (*algorithm[ccp->out_algorithm]->o.Term)(); - ccp->out_init = 0; + if (ccp->out.state != NULL) { + (*algorithm[ccp->out.algorithm]->o.Term)(ccp->out.state); + ccp->out.state = NULL; } } @@ -278,26 +304,29 @@ CcpLayerUp(struct fsm *fp) /* We're now up */ struct ccp *ccp = fsm2ccp(fp); LogPrintf(LogCCP, "CcpLayerUp.\n"); - if (!ccp->in_init && ccp->in_algorithm >= 0 && - ccp->in_algorithm < NALGORITHMS) - if ((*algorithm[ccp->in_algorithm]->i.Init)()) - ccp->in_init = 1; - else { + if (ccp->in.state == NULL && ccp->in.algorithm >= 0 && + ccp->in.algorithm < NALGORITHMS) { + ccp->in.state = (*algorithm[ccp->in.algorithm]->i.Init)(&ccp->in.opt); + if (ccp->in.state == NULL) { LogPrintf(LogERROR, "%s (in) initialisation failure\n", protoname(ccp->his_proto)); ccp->his_proto = ccp->my_proto = -1; FsmClose(fp); } - if (!ccp->out_init && ccp->out_algorithm >= 0 && - ccp->out_algorithm < NALGORITHMS) - if ((*algorithm[ccp->out_algorithm]->o.Init)()) - ccp->out_init = 1; - else { + } + + if (ccp->out.state == NULL && ccp->out.algorithm >= 0 && + ccp->out.algorithm < NALGORITHMS) { + ccp->out.state = (*algorithm[ccp->out.algorithm]->o.Init) + (&ccp->out.opt->val); + if (ccp->out.state == NULL) { LogPrintf(LogERROR, "%s (out) initialisation failure\n", protoname(ccp->my_proto)); ccp->his_proto = ccp->my_proto = -1; FsmClose(fp); } + } + LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n", protoname(ccp->my_proto), ccp->my_proto, protoname(ccp->his_proto), ccp->his_proto); @@ -311,19 +340,30 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, struct ccp *ccp = fsm2ccp(fp); int type, length; int f; + const char *end; while (plen >= sizeof(struct fsmconfig)) { type = *cp; length = cp[1]; - if (type < NCFTYPES) - LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length); - else - LogPrintf(LogCCP, " ???[%d]\n", length); + + if (length > sizeof(struct lcp_opt)) { + length = sizeof(struct lcp_opt); + LogPrintf(LogCCP, "Warning: Truncating length to %d\n", length); + } for (f = NALGORITHMS-1; f > -1; f--) if (algorithm[f]->id == type) break; + end = f == -1 ? "" : (*algorithm[f]->Disp)((struct lcp_opt *)cp); + if (end == NULL) + end = ""; + + if (type < NCFTYPES) + LogPrintf(LogCCP, " %s[%d] %s\n", cftypes[type], length, end); + else + LogPrintf(LogCCP, " ???[%d] %s\n", length, end); + if (f == -1) { /* Don't understand that :-( */ if (mode_type == MODE_REQ) { @@ -332,26 +372,26 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, dec->rejend += length; } } else { - struct lcp_opt o; + struct ccp_opt *o; switch (mode_type) { case MODE_REQ: - if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) { - memcpy(&o, cp, length); - switch ((*algorithm[f]->i.Set)(&o)) { + if (Acceptable(algorithm[f]->Conf) && ccp->in.algorithm == -1) { + memcpy(&ccp->in.opt, cp, length); + switch ((*algorithm[f]->i.Set)(&ccp->in.opt, &ccp->cfg)) { case MODE_REJ: - memcpy(dec->rejend, &o, o.len); - dec->rejend += o.len; + memcpy(dec->rejend, &ccp->in.opt, ccp->in.opt.len); + dec->rejend += ccp->in.opt.len; break; case MODE_NAK: - memcpy(dec->nakend, &o, o.len); - dec->nakend += o.len; + memcpy(dec->nakend, &ccp->in.opt, ccp->in.opt.len); + dec->nakend += ccp->in.opt.len; break; case MODE_ACK: memcpy(dec->ackend, cp, length); dec->ackend += length; ccp->his_proto = type; - ccp->in_algorithm = f; /* This one'll do ! */ + ccp->in.algorithm = f; /* This one'll do :-) */ break; } } else { @@ -360,12 +400,19 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, } break; case MODE_NAK: - memcpy(&o, cp, length); - if ((*algorithm[f]->o.Set)(&o) == MODE_ACK) - ccp->my_proto = algorithm[f]->id; + for (o = ccp->out.opt; o != NULL; o = o->next) + if (o->val.id == cp[0]) + break; + if (o == NULL) + LogPrintf(LogCCP, "Warning: Ignoring peer NAK of unsent option\n"); else { - ccp->his_reject |= (1 << type); - ccp->my_proto = -1; + memcpy(&o->val, cp, length); + if ((*algorithm[f]->o.Set)(&o->val) == MODE_ACK) + ccp->my_proto = algorithm[f]->id; + else { + ccp->his_reject |= (1 << type); + ccp->my_proto = -1; + } } break; case MODE_REJ: @@ -375,15 +422,24 @@ CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, } } - plen -= length; - cp += length; + plen -= cp[1]; + cp += cp[1]; } if (mode_type != MODE_NOP && dec->rejend != dec->rej) { - dec->ackend = dec->ack; /* let's not send both ! */ - if (!ccp->in_init) { + /* rejects are preferred */ + dec->ackend = dec->ack; + dec->nakend = dec->nak; + if (ccp->in.state == NULL) { ccp->his_proto = -1; - ccp->in_algorithm = -1; + ccp->in.algorithm = -1; + } + } else if (mode_type != MODE_NOP && dec->nakend != dec->nak) { + /* then NAKs */ + dec->ackend = dec->ack; + if (ccp->in.state == NULL) { + ccp->his_proto = -1; + ccp->in.algorithm = -1; } } } @@ -423,8 +479,8 @@ CcpRecvResetAck(struct fsm *fp, u_char id) ccp->last_reset = ccp->reset_sent; ccp->reset_sent = -1; - if (ccp->in_init) - (*algorithm[ccp->in_algorithm]->i.Reset)(); + if (ccp->in.state != NULL) + (*algorithm[ccp->in.algorithm]->i.Reset)(ccp->in.state); } int @@ -432,8 +488,10 @@ ccp_Output(struct ccp *ccp, struct link *l, int pri, u_short proto, struct mbuf *m) { /* Compress outgoing Network Layer data */ - if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && ccp->out_init) - return (*algorithm[ccp->out_algorithm]->o.Write)(ccp, l, pri, proto, m); + if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && + ccp->out.state != NULL) + return (*algorithm[ccp->out.algorithm]->o.Write) + (ccp->out.state, ccp, l, pri, proto, m); return 0; } @@ -451,13 +509,15 @@ ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp) /* Send another REQ and put the packet in the bit bucket */ LogPrintf(LogCCP, "ReSendResetReq(%d)\n", ccp->reset_sent); FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0); - } else if (ccp->in_init) - return (*algorithm[ccp->in_algorithm]->i.Read)(ccp, proto, bp); + } else if (ccp->in.state != NULL) + return (*algorithm[ccp->in.algorithm]->i.Read) + (ccp->in.state, ccp, proto, bp); pfree(bp); bp = NULL; - } else if ((*proto & 0xfff1) == 0x21 && ccp->in_init) + } else if ((*proto & 0xfff1) == 0x21 && ccp->in.state != NULL) /* Add incoming Network Layer traffic to our dictionary */ - (*algorithm[ccp->in_algorithm]->i.DictSetup)(ccp, *proto, bp); + (*algorithm[ccp->in.algorithm]->i.DictSetup) + (ccp->in.state, ccp, *proto, bp); return bp; } diff --git a/usr.sbin/ppp/ccp.h b/usr.sbin/ppp/ccp.h index dff8b0507b5..959a49594fd 100644 --- a/usr.sbin/ppp/ccp.h +++ b/usr.sbin/ppp/ccp.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ccp.h,v 1.14.2.11 1998/02/23 00:38:19 brian Exp $ + * $Id: ccp.h,v 1.14.2.12 1998/02/27 01:22:19 brian Exp $ * * TODO: */ @@ -35,6 +35,20 @@ #define TY_PPPD_DEFLATE 24 /* Deflate (gzip) - (mis) numbered by pppd */ #define TY_DEFLATE 26 /* Deflate (gzip) - rfc 1979 */ +struct ccp_config { + struct { + struct { + int winsize; + } in, out; + } deflate; +}; + +struct ccp_opt { + struct ccp_opt *next; + int algorithm; + struct lcp_opt val; +}; + struct ccp { struct fsm fsm; /* The finite state machine */ @@ -44,17 +58,25 @@ struct ccp { int reset_sent; /* If != -1, ignore compressed 'till ack */ int last_reset; /* We can receive more (dups) w/ this id */ - int in_algorithm; /* Incoming algorithm in use */ - int out_algorithm; /* Outgoing algorithm in use */ + struct { + int algorithm; /* Algorithm in use */ + void *state; /* Returned by implementations Init() */ + struct lcp_opt opt; /* Set by implementations OptInit() */ + } in; + + struct { + int algorithm; /* Algorithm in use */ + void *state; /* Returned by implementations Init() */ + struct ccp_opt *opt; /* Set by implementations OptInit() */ + } out; u_int32_t his_reject; /* Request codes rejected by peer */ u_int32_t my_reject; /* Request codes I have rejected */ - int out_init : 1; /* Init called for out algorithm */ - int in_init : 1; /* Init called for in algorithm */ - u_long uncompout, compout; u_long uncompin, compin; + + struct ccp_config cfg; }; #define fsm2ccp(fp) (fp->proto == PROTO_CCP ? (struct ccp *)fp : NULL) @@ -64,21 +86,21 @@ struct ccp_algorithm { int Conf; /* A Conf value from vars.h */ const char *(*Disp)(struct lcp_opt *); struct { - void (*Get)(struct lcp_opt *); - int (*Set)(struct lcp_opt *); - int (*Init)(void); - void (*Term)(void); - void (*Reset)(void); - struct mbuf *(*Read)(struct ccp *, u_short *, struct mbuf *); - void (*DictSetup)(struct ccp *, u_short, struct mbuf *); + int (*Set)(struct lcp_opt *, const struct ccp_config *); + void *(*Init)(struct lcp_opt *); + void (*Term)(void *); + void (*Reset)(void *); + struct mbuf *(*Read)(void *, struct ccp *, u_short *, struct mbuf *); + void (*DictSetup)(void *, struct ccp *, u_short, struct mbuf *); } i; struct { - void (*Get)(struct lcp_opt *); + void (*OptInit)(struct lcp_opt *, const struct ccp_config *); int (*Set)(struct lcp_opt *); - int (*Init)(void); - void (*Term)(void); - void (*Reset)(void); - int (*Write)(struct ccp *, struct link *, int, u_short, struct mbuf *); + void *(*Init)(struct lcp_opt *); + void (*Term)(void *); + void (*Reset)(void *); + int (*Write)(void *, struct ccp *, struct link *, int, u_short, + struct mbuf *); } o; }; diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 1657468ceaf..c196c3543a0 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.131.2.39 1998/03/16 22:51:58 brian Exp $ + * $Id: command.c,v 1.131.2.40 1998/03/16 22:53:38 brian Exp $ * */ #include @@ -1314,6 +1314,27 @@ SetVariable(struct cmdargs const *arg) cx->cfg.script.login[sizeof cx->cfg.script.login - 1] = '\0'; } break; + case VAR_WINSIZE: + if (arg->argc > 0) { + cx->ccp.cfg.deflate.out.winsize = atoi(arg->argv[0]); + if (cx->ccp.cfg.deflate.out.winsize < 8 || + cx->ccp.cfg.deflate.out.winsize > 15) { + LogPrintf(LogWARN, "%d: Invalid outgoing window size\n", + cx->ccp.cfg.deflate.out.winsize); + cx->ccp.cfg.deflate.out.winsize = 15; + } + if (arg->argc > 1) { + cx->ccp.cfg.deflate.in.winsize = atoi(arg->argv[1]); + if (cx->ccp.cfg.deflate.in.winsize < 8 || + cx->ccp.cfg.deflate.in.winsize > 15) { + LogPrintf(LogWARN, "%d: Invalid incoming window size\n", + cx->ccp.cfg.deflate.in.winsize); + cx->ccp.cfg.deflate.in.winsize = 15; + } + } else + cx->ccp.cfg.deflate.in.winsize = 0; + } + break; case VAR_DEVICE: Physical_SetDeviceList(cx->physical, argp); break; @@ -1385,6 +1406,9 @@ static struct cmdtab const SetCommands[] = { "Set authentication name", "set authname name", (const void *) VAR_AUTHNAME}, {"ctsrts", NULL, SetCtsRts, LOCAL_AUTH | LOCAL_CX, "Use CTS/RTS modem signalling", "set ctsrts [on|off]"}, + {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX, + "Set deflate window sizes", "set deflate out-winsize in-winsize", + (const void *) VAR_WINSIZE}, {"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX, "Set modem device name", "set device|line device-name[,device-name]", (const void *) VAR_DEVICE}, diff --git a/usr.sbin/ppp/command.h b/usr.sbin/ppp/command.h index 70279be5758..10626c5b41c 100644 --- a/usr.sbin/ppp/command.h +++ b/usr.sbin/ppp/command.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.h,v 1.12.2.3 1998/02/10 03:23:11 brian Exp $ + * $Id: command.h,v 1.12.2.4 1998/02/17 19:27:54 brian Exp $ * * TODO: */ @@ -45,12 +45,13 @@ struct cmdtab { #define VAR_DIAL 1 #define VAR_LOGIN 2 #define VAR_AUTHNAME 3 -#define VAR_DEVICE 4 -#define VAR_ACCMAP 5 -#define VAR_PHONE 6 -#define VAR_HANGUP 7 +#define VAR_WINSIZE 4 +#define VAR_DEVICE 5 +#define VAR_ACCMAP 6 +#define VAR_PHONE 7 +#define VAR_HANGUP 8 #ifdef HAVE_DES -#define VAR_ENC 8 +#define VAR_ENC 9 #endif extern struct in_addr ifnetmask; diff --git a/usr.sbin/ppp/deflate.c b/usr.sbin/ppp/deflate.c index 4ffb11fe1fe..88ea1547070 100644 --- a/usr.sbin/ppp/deflate.c +++ b/usr.sbin/ppp/deflate.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: deflate.c,v 1.6.4.6 1998/02/23 00:38:28 brian Exp $ + * $Id: deflate.c,v 1.6.4.7 1998/03/13 00:44:00 brian Exp $ */ #include @@ -54,30 +54,31 @@ struct deflate_state { u_short seqno; int uncomp_rec; + int winsize; z_stream cx; }; -static int iWindowSize = 15; -static int oWindowSize = 15; -static struct deflate_state InputState, OutputState; static char garbage[10]; static u_char EMPTY_BLOCK[4] = { 0x00, 0x00, 0xff, 0xff }; #define DEFLATE_CHUNK_LEN 1024 /* Allocate mbufs this size */ static void -DeflateResetOutput(void) +DeflateResetOutput(void *v) { - OutputState.seqno = 0; - OutputState.uncomp_rec = 0; - deflateReset(&OutputState.cx); + struct deflate_state *state = (struct deflate_state *)v; + + state->seqno = 0; + state->uncomp_rec = 0; + deflateReset(&state->cx); LogPrintf(LogCCP, "Deflate: Output channel reset\n"); } static int -DeflateOutput(struct ccp *ccp, struct link *l, int pri, u_short proto, +DeflateOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short proto, struct mbuf *mp) { + struct deflate_state *state = (struct deflate_state *)v; u_char *wp, *rp; int olen, ilen, len, res, flush; struct mbuf *mo_head, *mo, *mi_head, *mi; @@ -103,53 +104,53 @@ DeflateOutput(struct ccp *ccp, struct link *l, int pri, u_short proto, mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT); mo->cnt = 2; wp = MBUF_CTOP(mo); - *wp++ = OutputState.seqno >> 8; - *wp++ = OutputState.seqno & 0377; - LogPrintf(LogDEBUG, "DeflateOutput: Seq %d\n", OutputState.seqno); - OutputState.seqno++; + *wp++ = state->seqno >> 8; + *wp++ = state->seqno & 0377; + LogPrintf(LogDEBUG, "DeflateOutput: Seq %d\n", state->seqno); + state->seqno++; /* Set up the deflation context */ - OutputState.cx.next_out = wp; - OutputState.cx.avail_out = DEFLATE_CHUNK_LEN - 2; - OutputState.cx.next_in = MBUF_CTOP(mi); - OutputState.cx.avail_in = mi->cnt; + state->cx.next_out = wp; + state->cx.avail_out = DEFLATE_CHUNK_LEN - 2; + state->cx.next_in = MBUF_CTOP(mi); + state->cx.avail_in = mi->cnt; flush = Z_NO_FLUSH; olen = 0; while (1) { - if ((res = deflate(&OutputState.cx, flush)) != Z_OK) { + if ((res = deflate(&state->cx, flush)) != Z_OK) { if (res == Z_STREAM_END) break; /* Done */ LogPrintf(LogERROR, "DeflateOutput: deflate returned %d (%s)\n", - res, OutputState.cx.msg ? OutputState.cx.msg : ""); + res, state->cx.msg ? state->cx.msg : ""); pfree(mo_head); mbfree(mi_head); - OutputState.seqno--; + state->seqno--; return 1; /* packet dropped */ } - if (flush == Z_SYNC_FLUSH && OutputState.cx.avail_out != 0) + if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0) break; - if (OutputState.cx.avail_in == 0 && mi->next != NULL) { + if (state->cx.avail_in == 0 && mi->next != NULL) { mi = mi->next; - OutputState.cx.next_in = MBUF_CTOP(mi); - OutputState.cx.avail_in = mi->cnt; + state->cx.next_in = MBUF_CTOP(mi); + state->cx.avail_in = mi->cnt; if (mi->next == NULL) flush = Z_SYNC_FLUSH; } - if (OutputState.cx.avail_out == 0) { + if (state->cx.avail_out == 0) { mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_HDLCOUT); olen += (mo->cnt = DEFLATE_CHUNK_LEN); mo = mo->next; mo->cnt = 0; - OutputState.cx.next_out = MBUF_CTOP(mo); - OutputState.cx.avail_out = DEFLATE_CHUNK_LEN; + state->cx.next_out = MBUF_CTOP(mo); + state->cx.avail_out = DEFLATE_CHUNK_LEN; } } - olen += (mo->cnt = DEFLATE_CHUNK_LEN - OutputState.cx.avail_out); + olen += (mo->cnt = DEFLATE_CHUNK_LEN - state->cx.avail_out); olen -= 4; /* exclude the trailing EMPTY_BLOCK */ /* @@ -193,17 +194,20 @@ DeflateOutput(struct ccp *ccp, struct link *l, int pri, u_short proto, } static void -DeflateResetInput(void) +DeflateResetInput(void *v) { - InputState.seqno = 0; - InputState.uncomp_rec = 0; - inflateReset(&InputState.cx); + struct deflate_state *state = (struct deflate_state *)v; + + state->seqno = 0; + state->uncomp_rec = 0; + inflateReset(&state->cx); LogPrintf(LogCCP, "Deflate: Input channel reset\n"); } static struct mbuf * -DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) +DeflateInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mi) { + struct deflate_state *state = (struct deflate_state *)v; struct mbuf *mo, *mo_head, *mi_head; u_char *wp; int ilen, olen; @@ -217,24 +221,24 @@ DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) /* Check the sequence number. */ seq = (hdr[0] << 8) + hdr[1]; LogPrintf(LogDEBUG, "DeflateInput: Seq %d\n", seq); - if (seq != InputState.seqno) { - if (seq <= InputState.uncomp_rec) + if (seq != state->seqno) { + if (seq <= state->uncomp_rec) /* * So the peer's started at zero again - fine ! If we're wrong, * inflate() will fail. This is better than getting into a loop * trying to get a ResetReq to a busy sender. */ - InputState.seqno = seq; + state->seqno = seq; else { LogPrintf(LogERROR, "DeflateInput: Seq error: Got %d, expected %d\n", - seq, InputState.seqno); + seq, state->seqno); pfree(mi_head); CcpSendResetReq(&ccp->fsm); return NULL; } } - InputState.seqno++; - InputState.uncomp_rec = 0; + state->seqno++; + state->uncomp_rec = 0; /* Allocate an output mbuf */ mo_head = mo = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN); @@ -248,10 +252,10 @@ DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) * byte of the output and decide whether we have a compressed * proto field. */ - InputState.cx.next_in = MBUF_CTOP(mi); - InputState.cx.avail_in = mi->cnt; - InputState.cx.next_out = wp + 1; - InputState.cx.avail_out = 1; + state->cx.next_in = MBUF_CTOP(mi); + state->cx.avail_in = mi->cnt; + state->cx.next_out = wp + 1; + state->cx.avail_out = 1; ilen += mi->cnt; flush = mi->next ? Z_NO_FLUSH : Z_SYNC_FLUSH; @@ -259,45 +263,45 @@ DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) olen = 0; while (1) { - if ((res = inflate(&InputState.cx, flush)) != Z_OK) { + if ((res = inflate(&state->cx, flush)) != Z_OK) { if (res == Z_STREAM_END) break; /* Done */ LogPrintf(LogERROR, "DeflateInput: inflate returned %d (%s)\n", - res, InputState.cx.msg ? InputState.cx.msg : ""); + res, state->cx.msg ? state->cx.msg : ""); pfree(mo_head); pfree(mi); CcpSendResetReq(&ccp->fsm); return NULL; } - if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0) + if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0) break; - if (InputState.cx.avail_in == 0 && mi && (mi = mbfree(mi)) != NULL) { + if (state->cx.avail_in == 0 && mi && (mi = mbfree(mi)) != NULL) { /* underflow */ - InputState.cx.next_in = MBUF_CTOP(mi); - ilen += (InputState.cx.avail_in = mi->cnt); + state->cx.next_in = MBUF_CTOP(mi); + ilen += (state->cx.avail_in = mi->cnt); if (mi->next == NULL) flush = Z_SYNC_FLUSH; } - if (InputState.cx.avail_out == 0) + if (state->cx.avail_out == 0) /* overflow */ if (first) { if (!(wp[1] & 1)) { /* 2 byte proto, shuffle it back in output */ wp[0] = wp[1]; - InputState.cx.next_out--; - InputState.cx.avail_out = DEFLATE_CHUNK_LEN-1; + state->cx.next_out--; + state->cx.avail_out = DEFLATE_CHUNK_LEN-1; } else - InputState.cx.avail_out = DEFLATE_CHUNK_LEN-2; + state->cx.avail_out = DEFLATE_CHUNK_LEN-2; first = 0; } else { olen += (mo->cnt = DEFLATE_CHUNK_LEN); mo->next = mballoc(DEFLATE_CHUNK_LEN, MB_IPIN); mo = mo->next; - InputState.cx.next_out = MBUF_CTOP(mo); - InputState.cx.avail_out = DEFLATE_CHUNK_LEN; + state->cx.next_out = MBUF_CTOP(mo); + state->cx.avail_out = DEFLATE_CHUNK_LEN; } } @@ -311,7 +315,7 @@ DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) return NULL; } - olen += (mo->cnt = DEFLATE_CHUNK_LEN - InputState.cx.avail_out); + olen += (mo->cnt = DEFLATE_CHUNK_LEN - state->cx.avail_out); *proto = ((u_short)wp[0] << 8) | wp[1]; mo_head->offset += 2; @@ -328,24 +332,25 @@ DeflateInput(struct ccp *ccp, u_short *proto, struct mbuf *mi) * Simulate an EMPTY_BLOCK so that our dictionary stays in sync. * The peer will have silently removed this! */ - InputState.cx.next_out = garbage; - InputState.cx.avail_out = sizeof garbage; - InputState.cx.next_in = EMPTY_BLOCK; - InputState.cx.avail_in = sizeof EMPTY_BLOCK; - inflate(&InputState.cx, Z_SYNC_FLUSH); + state->cx.next_out = garbage; + state->cx.avail_out = sizeof garbage; + state->cx.next_in = EMPTY_BLOCK; + state->cx.avail_in = sizeof EMPTY_BLOCK; + inflate(&state->cx, Z_SYNC_FLUSH); return mo_head; } static void -DeflateDictSetup(struct ccp *ccp, u_short proto, struct mbuf *mi) +DeflateDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) { + struct deflate_state *state = (struct deflate_state *)v; int res, flush, expect_error; u_char *rp; struct mbuf *mi_head; short len; - LogPrintf(LogDEBUG, "DeflateDictSetup: Got seq %d\n", InputState.seqno); + LogPrintf(LogDEBUG, "DeflateDictSetup: Got seq %d\n", state->seqno); /* * Stuff an ``uncompressed data'' block header followed by the @@ -372,41 +377,41 @@ DeflateDictSetup(struct ccp *ccp, u_short proto, struct mbuf *mi) rp[3] = (~len) & 0377; /* One's compliment of the length */ rp[4] = (~len) >> 8; - InputState.cx.next_in = rp; - InputState.cx.avail_in = mi->cnt; - InputState.cx.next_out = garbage; - InputState.cx.avail_out = sizeof garbage; + state->cx.next_in = rp; + state->cx.avail_in = mi->cnt; + state->cx.next_out = garbage; + state->cx.avail_out = sizeof garbage; flush = Z_NO_FLUSH; expect_error = 0; while (1) { - if ((res = inflate(&InputState.cx, flush)) != Z_OK) { + if ((res = inflate(&state->cx, flush)) != Z_OK) { if (res == Z_STREAM_END) break; /* Done */ if (expect_error && res == Z_BUF_ERROR) break; LogPrintf(LogERROR, "DeflateDictSetup: inflate returned %d (%s)\n", - res, InputState.cx.msg ? InputState.cx.msg : ""); + res, state->cx.msg ? state->cx.msg : ""); LogPrintf(LogERROR, "DeflateDictSetup: avail_in %d, avail_out %d\n", - InputState.cx.avail_in, InputState.cx.avail_out); + state->cx.avail_in, state->cx.avail_out); CcpSendResetReq(&ccp->fsm); mbfree(mi_head); /* lose our allocated ``head'' buf */ return; } - if (flush == Z_SYNC_FLUSH && InputState.cx.avail_out != 0) + if (flush == Z_SYNC_FLUSH && state->cx.avail_out != 0) break; - if (InputState.cx.avail_in == 0 && mi && (mi = mi->next) != NULL) { + if (state->cx.avail_in == 0 && mi && (mi = mi->next) != NULL) { /* underflow */ - InputState.cx.next_in = MBUF_CTOP(mi); - InputState.cx.avail_in = mi->cnt; + state->cx.next_in = MBUF_CTOP(mi); + state->cx.avail_in = mi->cnt; if (mi->next == NULL) flush = Z_SYNC_FLUSH; } - if (InputState.cx.avail_out == 0) { - if (InputState.cx.avail_in == 0) + if (state->cx.avail_out == 0) { + if (state->cx.avail_in == 0) /* * This seems to be a bug in libz ! If inflate() finished * with 0 avail_in and 0 avail_out *and* this is the end of @@ -420,16 +425,16 @@ DeflateDictSetup(struct ccp *ccp, u_short proto, struct mbuf *mi) */ expect_error = 1; /* overflow */ - InputState.cx.next_out = garbage; - InputState.cx.avail_out = sizeof garbage; + state->cx.next_out = garbage; + state->cx.avail_out = sizeof garbage; } } ccp->compin += len; ccp->uncompin += len; - InputState.seqno++; - InputState.uncomp_rec++; + state->seqno++; + state->uncomp_rec++; mbfree(mi_head); /* lose our allocated ``head'' buf */ } @@ -443,50 +448,21 @@ DeflateDispOpts(struct lcp_opt *o) } static void -DeflateGetInputOpts(struct lcp_opt *o) +DeflateInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { - o->id = TY_DEFLATE; o->len = 4; - o->data[0] = ((iWindowSize-8)<<4)+8; - o->data[1] = '\0'; -} - -static void -DeflateGetOutputOpts(struct lcp_opt *o) -{ - o->id = TY_DEFLATE; - o->len = 4; - o->data[0] = ((oWindowSize-8)<<4)+8; - o->data[1] = '\0'; -} - -static void -PppdDeflateGetInputOpts(struct lcp_opt *o) -{ - o->id = TY_PPPD_DEFLATE; - o->len = 4; - o->data[0] = ((iWindowSize-8)<<4)+8; - o->data[1] = '\0'; -} - -static void -PppdDeflateGetOutputOpts(struct lcp_opt *o) -{ - o->id = TY_PPPD_DEFLATE; - o->len = 4; - o->data[0] = ((oWindowSize-8)<<4)+8; + o->data[0] = ((cfg->deflate.out.winsize - 8) << 4) + 8; o->data[1] = '\0'; } static int -DeflateSetOpts(struct lcp_opt *o, int *sz) +DeflateSetOptsOutput(struct lcp_opt *o) { - if (o->len != 4 || (o->data[0]&15) != 8 || o->data[1] != '\0') { + if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0') return MODE_REJ; - } - *sz = (o->data[0] >> 4) + 8; - if (*sz > 15) { - *sz = 15; + + if ((o->data[0] >> 4) + 8 > 15) { + o->data[0] = ((15 - 8) << 4) + 8; return MODE_NAK; } @@ -494,84 +470,89 @@ DeflateSetOpts(struct lcp_opt *o, int *sz) } static int -DeflateSetInputOpts(struct lcp_opt *o) +DeflateSetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) { - int res; - res = DeflateSetOpts(o, &iWindowSize); - if (res != MODE_ACK) - DeflateGetInputOpts(o); - return res; + int want; + + if (o->len != 4 || (o->data[0] & 15) != 8 || o->data[1] != '\0') + return MODE_REJ; + + want = (o->data[0] >> 4) + 8; + if (cfg->deflate.in.winsize == 0) { + if (want < 8 || want > 15) { + o->data[0] = ((15 - 8) << 4) + 8; + } + } else if (want != cfg->deflate.in.winsize) { + o->data[0] = ((cfg->deflate.in.winsize - 8) << 4) + 8; + return MODE_NAK; + } + + return MODE_ACK; } -static int -DeflateSetOutputOpts(struct lcp_opt *o) +static void * +DeflateInitInput(struct lcp_opt *o) { - int res; - res = DeflateSetOpts(o, &oWindowSize); - if (res != MODE_ACK) - DeflateGetOutputOpts(o); - return res; + struct deflate_state *state; + + state = (struct deflate_state *)malloc(sizeof(struct deflate_state)); + if (state != NULL) { + state->winsize = (o->data[0] >> 4) + 8; + state->cx.zalloc = NULL; + state->cx.opaque = NULL; + state->cx.zfree = NULL; + state->cx.next_out = NULL; + if (inflateInit2(&state->cx, -state->winsize) == Z_OK) + DeflateResetInput(state); + else { + free(state); + state = NULL; + } + } + + return state; } -static int -PppdDeflateSetInputOpts(struct lcp_opt *o) +static void * +DeflateInitOutput(struct lcp_opt *o) { - int res; - res = DeflateSetOpts(o, &iWindowSize); - if (res != MODE_ACK) - PppdDeflateGetInputOpts(o); - return res; -} + struct deflate_state *state; -static int -PppdDeflateSetOutputOpts(struct lcp_opt *o) -{ - int res; - res = DeflateSetOpts(o, &oWindowSize); - if (res != MODE_ACK) - PppdDeflateGetOutputOpts(o); - return res; -} + state = (struct deflate_state *)malloc(sizeof(struct deflate_state)); + if (state != NULL) { + state->winsize = (o->data[0] >> 4) + 8; + state->cx.zalloc = NULL; + state->cx.opaque = NULL; + state->cx.zfree = NULL; + state->cx.next_in = NULL; + if (deflateInit2(&state->cx, Z_DEFAULT_COMPRESSION, 8, + -state->winsize, 8, Z_DEFAULT_STRATEGY) == Z_OK) + DeflateResetOutput(state); + else { + free(state); + state = NULL; + } + } -static int -DeflateInitInput(void) -{ - InputState.cx.zalloc = NULL; - InputState.cx.opaque = NULL; - InputState.cx.zfree = NULL; - InputState.cx.next_out = NULL; - if (inflateInit2(&InputState.cx, -iWindowSize) != Z_OK) - return 0; - DeflateResetInput(); - return 1; -} - -static int -DeflateInitOutput(void) -{ - OutputState.cx.zalloc = NULL; - OutputState.cx.opaque = NULL; - OutputState.cx.zfree = NULL; - OutputState.cx.next_in = NULL; - if (deflateInit2(&OutputState.cx, Z_DEFAULT_COMPRESSION, 8, - -oWindowSize, 8, Z_DEFAULT_STRATEGY) != Z_OK) - return 0; - DeflateResetOutput(); - return 1; + return state; } static void -DeflateTermInput(void) +DeflateTermInput(void *v) { - iWindowSize = 15; - inflateEnd(&InputState.cx); + struct deflate_state *state = (struct deflate_state *)v; + + inflateEnd(&state->cx); + free(state); } static void -DeflateTermOutput(void) +DeflateTermOutput(void *v) { - oWindowSize = 15; - deflateEnd(&OutputState.cx); + struct deflate_state *state = (struct deflate_state *)v; + + deflateEnd(&state->cx); + free(state); } const struct ccp_algorithm PppdDeflateAlgorithm = { @@ -579,8 +560,7 @@ const struct ccp_algorithm PppdDeflateAlgorithm = { ConfPppdDeflate, DeflateDispOpts, { - PppdDeflateGetInputOpts, - PppdDeflateSetInputOpts, + DeflateSetOptsInput, DeflateInitInput, DeflateTermInput, DeflateResetInput, @@ -588,8 +568,8 @@ const struct ccp_algorithm PppdDeflateAlgorithm = { DeflateDictSetup }, { - PppdDeflateGetOutputOpts, - PppdDeflateSetOutputOpts, + DeflateInitOptsOutput, + DeflateSetOptsOutput, DeflateInitOutput, DeflateTermOutput, DeflateResetOutput, @@ -602,8 +582,7 @@ const struct ccp_algorithm DeflateAlgorithm = { ConfDeflate, DeflateDispOpts, { - DeflateGetInputOpts, - DeflateSetInputOpts, + DeflateSetOptsInput, DeflateInitInput, DeflateTermInput, DeflateResetInput, @@ -611,8 +590,8 @@ const struct ccp_algorithm DeflateAlgorithm = { DeflateDictSetup }, { - DeflateGetOutputOpts, - DeflateSetOutputOpts, + DeflateInitOptsOutput, + DeflateSetOptsOutput, DeflateInitOutput, DeflateTermOutput, DeflateResetOutput, diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index 526c73462af..9ab76075a24 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.97.2.4 1998/03/16 07:37:56 brian Exp $ +.\" $Id: ppp.8,v 1.97.2.5 1998/03/16 22:52:42 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 @@ -1997,6 +1997,20 @@ for security reasons. This sets the authentication id used in client mode PAP or CHAP negotiation. .It set ctsrts This sets hardware flow control and is the default. +.It set deflate out-winsize [in-winsize] +This sets the DEFLATE algorithms default outgoing and incoming window +sizes. Both +.Ar out-winsize +and +.Ar in-winsize +must be values between +.Em 8 +and +.Em 15 . +If +.Ar in-winsize +is specified, ppp will insist that this window size is used and will not +accept any other values from the peer. .It set device|line value[,value...] This sets the device(s) to which .Nm diff --git a/usr.sbin/ppp/pred.c b/usr.sbin/ppp/pred.c index c69613d99c1..0150b8d6bb0 100644 --- a/usr.sbin/ppp/pred.c +++ b/usr.sbin/ppp/pred.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pred.c,v 1.20.2.4 1998/02/23 00:38:41 brian Exp $ + * $Id: pred.c,v 1.20.2.5 1998/03/13 00:44:22 brian Exp $ */ #include @@ -59,16 +59,16 @@ * A better hash function would result in additional compression, * at the expense of time. */ -#define IHASH(x) do {iHash = (iHash << 4) ^ (x);} while(0) -#define OHASH(x) do {oHash = (oHash << 4) ^ (x);} while(0) +#define HASH(state, x) state->hash = (state->hash << 4) ^ (x) #define GUESS_TABLE_SIZE 65536 -static unsigned short int iHash, oHash; -static unsigned char *InputGuessTable; -static unsigned char *OutputGuessTable; +struct pred1_state { + u_short hash; + u_char dict[GUESS_TABLE_SIZE]; +}; static int -compress(u_char * source, u_char * dest, int len) +compress(struct pred1_state *state, u_char *source, u_char *dest, int len) { int i, bitmask; unsigned char *flagdest, flags, *orgdest; @@ -78,13 +78,13 @@ compress(u_char * source, u_char * dest, int len) flagdest = dest++; flags = 0; /* All guess wrong initially */ for (bitmask = 1, i = 0; i < 8 && len; i++, bitmask <<= 1) { - if (OutputGuessTable[oHash] == *source) { + if (state->dict[state->hash] == *source) { flags |= bitmask; /* Guess was right - don't output */ } else { - OutputGuessTable[oHash] = *source; + state->dict[state->hash] = *source; *dest++ = *source; /* Guess wrong, output char */ } - OHASH(*source++); + HASH(state, *source++); len--; } *flagdest = flags; @@ -93,19 +93,17 @@ compress(u_char * source, u_char * dest, int len) } static void -SyncTable(u_char * source, u_char * dest, int len) +SyncTable(struct pred1_state *state, u_char * source, u_char * dest, int len) { - while (len--) { - if (InputGuessTable[iHash] != *source) { - InputGuessTable[iHash] = *source; - } - IHASH(*dest++ = *source++); + if (state->dict[state->hash] != *source) + state->dict[state->hash] = *source; + HASH(state, *dest++ = *source++); } } static int -decompress(u_char * source, u_char * dest, int len) +decompress(struct pred1_state *state, u_char * source, u_char * dest, int len) { int i, bitmask; unsigned char flags, *orgdest; @@ -116,78 +114,70 @@ decompress(u_char * source, u_char * dest, int len) len--; for (i = 0, bitmask = 1; i < 8; i++, bitmask <<= 1) { if (flags & bitmask) { - *dest = InputGuessTable[iHash]; /* Guess correct */ + *dest = state->dict[state->hash]; /* Guess correct */ } else { if (!len) break; /* we seem to be really done -- cabo */ - InputGuessTable[iHash] = *source; /* Guess wrong */ + state->dict[state->hash] = *source; /* Guess wrong */ *dest = *source++; /* Read from source */ len--; } - IHASH(*dest++); + HASH(state, *dest++); } } return (dest - orgdest); } static void -Pred1TermInput(void) +Pred1Term(void *v) { - if (InputGuessTable != NULL) { - free(InputGuessTable); - InputGuessTable = NULL; - } + struct pred1_state *state = (struct pred1_state *)v; + free(state); } static void -Pred1TermOutput(void) +Pred1ResetInput(void *v) { - if (OutputGuessTable != NULL) { - free(OutputGuessTable); - OutputGuessTable = NULL; - } -} - -static void -Pred1ResetInput(void) -{ - iHash = 0; - memset(InputGuessTable, '\0', GUESS_TABLE_SIZE); + struct pred1_state *state = (struct pred1_state *)v; + state->hash = 0; + memset(state->dict, '\0', sizeof state->dict); LogPrintf(LogCCP, "Predictor1: Input channel reset\n"); } static void -Pred1ResetOutput(void) +Pred1ResetOutput(void *v) { - oHash = 0; - memset(OutputGuessTable, '\0', GUESS_TABLE_SIZE); + struct pred1_state *state = (struct pred1_state *)v; + state->hash = 0; + memset(state->dict, '\0', sizeof state->dict); LogPrintf(LogCCP, "Predictor1: Output channel reset\n"); } -static int -Pred1InitInput(void) +static void * +Pred1InitInput(struct lcp_opt *o) { - if (InputGuessTable == NULL) - if ((InputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL) - return 0; - Pred1ResetInput(); - return 1; + struct pred1_state *state; + state = (struct pred1_state *)malloc(sizeof(struct pred1_state)); + if (state != NULL) + Pred1ResetInput(state); + return state; +} + +static void * +Pred1InitOutput(struct lcp_opt *o) +{ + struct pred1_state *state; + state = (struct pred1_state *)malloc(sizeof(struct pred1_state)); + if (state != NULL) + Pred1ResetOutput(state); + return state; } static int -Pred1InitOutput(void) -{ - if (OutputGuessTable == NULL) - if ((OutputGuessTable = malloc(GUESS_TABLE_SIZE)) == NULL) - return 0; - Pred1ResetOutput(); - return 1; -} - -static int -Pred1Output(struct ccp *ccp, struct link *l, int pri, u_short proto, +Pred1Output(void *v, struct ccp *ccp, struct link *l, int pri, u_short proto, struct mbuf *bp) { + struct pred1_state *state = (struct pred1_state *)v; struct mbuf *mwp; u_char *cp, *wp, *hp; int orglen, len; @@ -206,7 +196,7 @@ Pred1Output(struct ccp *ccp, struct link *l, int pri, u_short proto, fcs = HdlcFcs(INITFCS, bufp, 2 + orglen); fcs = ~fcs; - len = compress(bufp + 2, wp, orglen); + len = compress(state, bufp + 2, wp, orglen); LogPrintf(LogDEBUG, "Pred1Output: orglen (%d) --> len (%d)\n", orglen, len); ccp->uncompout += orglen; if (len < orglen) { @@ -227,8 +217,9 @@ Pred1Output(struct ccp *ccp, struct link *l, int pri, u_short proto, } static struct mbuf * -Pred1Input(struct ccp *ccp, u_short *proto, struct mbuf *bp) +Pred1Input(void *v, struct ccp *ccp, u_short *proto, struct mbuf *bp) { + struct pred1_state *state = (struct pred1_state *)v; u_char *cp, *pp; int len, olen, len1; struct mbuf *wp; @@ -245,7 +236,7 @@ Pred1Input(struct ccp *ccp, u_short *proto, struct mbuf *bp) len += *cp++; ccp->uncompin += len & 0x7fff; if (len & 0x8000) { - len1 = decompress(cp, pp, olen - 4); + len1 = decompress(state, cp, pp, olen - 4); ccp->compin += olen; len &= 0x7fff; if (len != len1) { /* Error is detected. Send reset request */ @@ -259,7 +250,7 @@ Pred1Input(struct ccp *ccp, u_short *proto, struct mbuf *bp) pp += len1; } else { ccp->compin += len; - SyncTable(cp, pp, len); + SyncTable(state, cp, pp, len); cp += len; pp += len; } @@ -295,7 +286,7 @@ Pred1Input(struct ccp *ccp, u_short *proto, struct mbuf *bp) } static void -Pred1DictSetup(struct ccp *ccp, u_short proto, struct mbuf * bp) +Pred1DictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf * bp) { } @@ -306,40 +297,44 @@ Pred1DispOpts(struct lcp_opt *o) } static void -Pred1GetOpts(struct lcp_opt *o) +Pred1InitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) { - o->id = TY_PRED1; o->len = 2; } static int -Pred1SetOpts(struct lcp_opt *o) +Pred1SetOptsOutput(struct lcp_opt *o) { - if (o->id != TY_PRED1 || o->len != 2) { - Pred1GetOpts(o); + if (o->len != 2) { + o->len = 2; return MODE_NAK; } return MODE_ACK; } +static int +Pred1SetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) +{ + return Pred1SetOptsOutput(o); +} + const struct ccp_algorithm Pred1Algorithm = { TY_PRED1, ConfPred1, Pred1DispOpts, { - Pred1GetOpts, - Pred1SetOpts, + Pred1SetOptsInput, Pred1InitInput, - Pred1TermInput, + Pred1Term, Pred1ResetInput, Pred1Input, Pred1DictSetup }, { - Pred1GetOpts, - Pred1SetOpts, + Pred1InitOptsOutput, + Pred1SetOptsOutput, Pred1InitOutput, - Pred1TermOutput, + Pred1Term, Pred1ResetOutput, Pred1Output },