xref: /freebsd/usr.sbin/ppp/ccp.c (revision 6d6667755ecffdeb3518255e2b482ebe03333c35)
11ae349f5Scvs2svn /*
21ae349f5Scvs2svn  *	   PPP Compression Control Protocol (CCP) Module
31ae349f5Scvs2svn  *
41ae349f5Scvs2svn  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51ae349f5Scvs2svn  *
61ae349f5Scvs2svn  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
71ae349f5Scvs2svn  *
81ae349f5Scvs2svn  * Redistribution and use in source and binary forms are permitted
91ae349f5Scvs2svn  * provided that the above copyright notice and this paragraph are
101ae349f5Scvs2svn  * duplicated in all such forms and that any documentation,
111ae349f5Scvs2svn  * advertising materials, and other materials related to such
121ae349f5Scvs2svn  * distribution and use acknowledge that the software was developed
131ae349f5Scvs2svn  * by the Internet Initiative Japan, Inc.  The name of the
141ae349f5Scvs2svn  * IIJ may not be used to endorse or promote products derived
151ae349f5Scvs2svn  * from this software without specific prior written permission.
161ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171ae349f5Scvs2svn  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181ae349f5Scvs2svn  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191ae349f5Scvs2svn  *
206d666775SBrian Somers  * $Id: ccp.c,v 1.30.2.14 1998/02/24 03:36:45 brian Exp $
211ae349f5Scvs2svn  *
221ae349f5Scvs2svn  *	TODO:
231ae349f5Scvs2svn  *		o Support other compression protocols
241ae349f5Scvs2svn  */
251ae349f5Scvs2svn #include <sys/param.h>
261ae349f5Scvs2svn #include <netinet/in.h>
271ae349f5Scvs2svn 
281ae349f5Scvs2svn #include <stdio.h>
291ae349f5Scvs2svn #include <string.h>
3085b542cfSBrian Somers #include <termios.h>
311ae349f5Scvs2svn 
321ae349f5Scvs2svn #include "command.h"
331ae349f5Scvs2svn #include "mbuf.h"
341ae349f5Scvs2svn #include "log.h"
351ae349f5Scvs2svn #include "defs.h"
361ae349f5Scvs2svn #include "timer.h"
371ae349f5Scvs2svn #include "fsm.h"
381ae349f5Scvs2svn #include "lcpproto.h"
391ae349f5Scvs2svn #include "lcp.h"
401ae349f5Scvs2svn #include "ccp.h"
411ae349f5Scvs2svn #include "loadalias.h"
421ae349f5Scvs2svn #include "vars.h"
431ae349f5Scvs2svn #include "pred.h"
441ae349f5Scvs2svn #include "deflate.h"
45455aabc3SBrian Somers #include "bundle.h"
4685b542cfSBrian Somers #include "descriptor.h"
4785b542cfSBrian Somers #include "prompt.h"
48503a7782SBrian Somers #include "hdlc.h"
49503a7782SBrian Somers #include "throughput.h"
50503a7782SBrian Somers #include "link.h"
51503a7782SBrian Somers #include "chat.h"
52503a7782SBrian Somers #include "datalink.h"
531ae349f5Scvs2svn 
541ae349f5Scvs2svn static void CcpSendConfigReq(struct fsm *);
551ae349f5Scvs2svn static void CcpSendTerminateReq(struct fsm *);
561ae349f5Scvs2svn static void CcpSendTerminateAck(struct fsm *);
5783d1af55SBrian Somers static void CcpDecodeConfig(struct fsm *, u_char *, int, int);
581ae349f5Scvs2svn static void CcpLayerStart(struct fsm *);
591ae349f5Scvs2svn static void CcpLayerFinish(struct fsm *);
601ae349f5Scvs2svn static void CcpLayerUp(struct fsm *);
611ae349f5Scvs2svn static void CcpLayerDown(struct fsm *);
621ae349f5Scvs2svn static void CcpInitRestartCounter(struct fsm *);
63503a7782SBrian Somers static void CcpRecvResetReq(struct fsm *);
64503a7782SBrian Somers static void CcpRecvResetAck(struct fsm *, u_char);
651ae349f5Scvs2svn 
6683d1af55SBrian Somers static struct fsm_callbacks ccp_Callbacks = {
6783d1af55SBrian Somers   CcpLayerUp,
6883d1af55SBrian Somers   CcpLayerDown,
6983d1af55SBrian Somers   CcpLayerStart,
706d666775SBrian Somers   CcpLayerFinish,
7183d1af55SBrian Somers   CcpInitRestartCounter,
7283d1af55SBrian Somers   CcpSendConfigReq,
7383d1af55SBrian Somers   CcpSendTerminateReq,
7483d1af55SBrian Somers   CcpSendTerminateAck,
75503a7782SBrian Somers   CcpDecodeConfig,
76503a7782SBrian Somers   CcpRecvResetReq,
77503a7782SBrian Somers   CcpRecvResetAck
7883d1af55SBrian Somers };
7983d1af55SBrian Somers 
801ae349f5Scvs2svn static char const *cftypes[] = {
811ae349f5Scvs2svn   /* Check out the latest ``Compression Control Protocol'' rfc (rfc1962.txt) */
821ae349f5Scvs2svn   "OUI",		/* 0: OUI */
831ae349f5Scvs2svn   "PRED1",		/* 1: Predictor type 1 */
841ae349f5Scvs2svn   "PRED2",		/* 2: Predictor type 2 */
851ae349f5Scvs2svn   "PUDDLE",		/* 3: Puddle Jumber */
861ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
871ae349f5Scvs2svn   "???", "???", "???", "???", "???", "???",
881ae349f5Scvs2svn   "HWPPC",		/* 16: Hewlett-Packard PPC */
891ae349f5Scvs2svn   "STAC",		/* 17: Stac Electronics LZS (rfc1974) */
901ae349f5Scvs2svn   "MSPPC",		/* 18: Microsoft PPC */
911ae349f5Scvs2svn   "GAND",		/* 19: Gandalf FZA (rfc1993) */
921ae349f5Scvs2svn   "V42BIS",		/* 20: ARG->DATA.42bis compression */
931ae349f5Scvs2svn   "BSD",		/* 21: BSD LZW Compress */
941ae349f5Scvs2svn   "???",
951ae349f5Scvs2svn   "LZS-DCP",		/* 23: LZS-DCP Compression Protocol (rfc1967) */
961ae349f5Scvs2svn   "MAGNALINK/DEFLATE",	/* 24: Magnalink Variable Resource (rfc1975) */
971ae349f5Scvs2svn 			/* 24: Deflate (according to pppd-2.3.1) */
981ae349f5Scvs2svn   "DCE",		/* 25: Data Circuit-Terminating Equip (rfc1976) */
991ae349f5Scvs2svn   "DEFLATE",		/* 26: Deflate (rfc1979) */
1001ae349f5Scvs2svn };
1011ae349f5Scvs2svn 
1021ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
1031ae349f5Scvs2svn 
1041ae349f5Scvs2svn static const char *
1051ae349f5Scvs2svn protoname(int proto)
1061ae349f5Scvs2svn {
1071ae349f5Scvs2svn   if (proto < 0 || proto > NCFTYPES)
1081ae349f5Scvs2svn     return "none";
1091ae349f5Scvs2svn   return cftypes[proto];
1101ae349f5Scvs2svn }
1111ae349f5Scvs2svn 
1121ae349f5Scvs2svn /* We support these algorithms, and Req them in the given order */
1131ae349f5Scvs2svn static const struct ccp_algorithm *algorithm[] = {
1141ae349f5Scvs2svn   &DeflateAlgorithm,
1151ae349f5Scvs2svn   &Pred1Algorithm,
1161ae349f5Scvs2svn   &PppdDeflateAlgorithm
1171ae349f5Scvs2svn };
1181ae349f5Scvs2svn 
1191ae349f5Scvs2svn #define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
1201ae349f5Scvs2svn 
1211ae349f5Scvs2svn int
122503a7782SBrian Somers ccp_ReportStatus(struct cmdargs const *arg)
1231ae349f5Scvs2svn {
124503a7782SBrian Somers   struct ccp *ccp = bundle2ccp(arg->bundle, arg->cx ? arg->cx->name : NULL);
125503a7782SBrian Somers 
126503a7782SBrian Somers   prompt_Printf(&prompt, "%s [%s]\n", ccp->fsm.name,
127503a7782SBrian Somers                 StateNames[ccp->fsm.state]);
12885b542cfSBrian Somers   prompt_Printf(&prompt, "My protocol = %s, His protocol = %s\n",
129503a7782SBrian Somers                 protoname(ccp->my_proto), protoname(ccp->his_proto));
13085b542cfSBrian Somers   prompt_Printf(&prompt, "Output: %ld --> %ld,  Input: %ld --> %ld\n",
131503a7782SBrian Somers                 ccp->uncompout, ccp->compout,
132503a7782SBrian Somers                 ccp->compin, ccp->uncompin);
1331ae349f5Scvs2svn   return 0;
1341ae349f5Scvs2svn }
1351ae349f5Scvs2svn 
1361ae349f5Scvs2svn void
1376d666775SBrian Somers ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
1386d666775SBrian Somers          const struct fsm_parent *parent)
1391ae349f5Scvs2svn {
1407308ec68SBrian Somers   /* Initialise ourselves */
141f4768038SBrian Somers   fsm_Init(&ccp->fsm, "CCP", PROTO_CCP, CCP_MAXCODE, 10, LogCCP,
1426d666775SBrian Somers            bundle, l, parent, &ccp_Callbacks);
143503a7782SBrian Somers   ccp_Setup(ccp);
144503a7782SBrian Somers }
145503a7782SBrian Somers 
146503a7782SBrian Somers void
147503a7782SBrian Somers ccp_Setup(struct ccp *ccp)
148503a7782SBrian Somers {
149503a7782SBrian Somers   /* Set ourselves up for a startup */
150503a7782SBrian Somers   ccp->fsm.open_mode = 0;
151503a7782SBrian Somers   ccp->his_proto = ccp->my_proto = -1;
152503a7782SBrian Somers   ccp->reset_sent = ccp->last_reset = -1;
153503a7782SBrian Somers   ccp->in_algorithm = ccp->out_algorithm = -1;
154503a7782SBrian Somers   ccp->his_reject = ccp->my_reject = 0;
155503a7782SBrian Somers   ccp->out_init = ccp->in_init = 0;
156503a7782SBrian Somers   ccp->uncompout = ccp->compout = 0;
157503a7782SBrian Somers   ccp->uncompin = ccp->compin = 0;
1581ae349f5Scvs2svn }
1591ae349f5Scvs2svn 
1601ae349f5Scvs2svn static void
1611ae349f5Scvs2svn CcpInitRestartCounter(struct fsm *fp)
1621ae349f5Scvs2svn {
1637308ec68SBrian Somers   /* Set fsm timer load */
1641ae349f5Scvs2svn   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
1651ae349f5Scvs2svn   fp->restart = 5;
1661ae349f5Scvs2svn }
1671ae349f5Scvs2svn 
1681ae349f5Scvs2svn static void
1691ae349f5Scvs2svn CcpSendConfigReq(struct fsm *fp)
1701ae349f5Scvs2svn {
1717308ec68SBrian Somers   /* Send config REQ please */
172aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1731ae349f5Scvs2svn   u_char *cp;
1741ae349f5Scvs2svn   int f;
1751ae349f5Scvs2svn 
1761ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendConfigReq\n");
1771ae349f5Scvs2svn   cp = ReqBuff;
17883d1af55SBrian Somers   ccp->my_proto = -1;
17983d1af55SBrian Somers   ccp->out_algorithm = -1;
1801ae349f5Scvs2svn   for (f = 0; f < NALGORITHMS; f++)
18183d1af55SBrian Somers     if (Enabled(algorithm[f]->Conf) && !REJECTED(ccp, algorithm[f]->id)) {
1821ae349f5Scvs2svn       struct lcp_opt o;
1831ae349f5Scvs2svn 
1841ae349f5Scvs2svn       (*algorithm[f]->o.Get)(&o);
1851ae349f5Scvs2svn       cp += LcpPutConf(LogCCP, cp, &o, cftypes[o.id],
1861ae349f5Scvs2svn                        (*algorithm[f]->Disp)(&o));
18783d1af55SBrian Somers       ccp->my_proto = o.id;
18883d1af55SBrian Somers       ccp->out_algorithm = f;
1891ae349f5Scvs2svn     }
1901ae349f5Scvs2svn   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
1911ae349f5Scvs2svn }
1921ae349f5Scvs2svn 
1931ae349f5Scvs2svn void
1941ae349f5Scvs2svn CcpSendResetReq(struct fsm *fp)
1951ae349f5Scvs2svn {
1967308ec68SBrian Somers   /* We can't read our input - ask peer to reset */
197aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
1981ae349f5Scvs2svn   LogPrintf(LogCCP, "SendResetReq(%d)\n", fp->reqid);
19983d1af55SBrian Somers   ccp->reset_sent = fp->reqid;
20083d1af55SBrian Somers   ccp->last_reset = -1;
2011ae349f5Scvs2svn   FsmOutput(fp, CODE_RESETREQ, fp->reqid, NULL, 0);
2021ae349f5Scvs2svn }
2031ae349f5Scvs2svn 
2041ae349f5Scvs2svn static void
2051ae349f5Scvs2svn CcpSendTerminateReq(struct fsm *fp)
2061ae349f5Scvs2svn {
2077308ec68SBrian Somers   /* Term REQ just sent by FSM */
2081ae349f5Scvs2svn }
2091ae349f5Scvs2svn 
2101ae349f5Scvs2svn static void
2111ae349f5Scvs2svn CcpSendTerminateAck(struct fsm *fp)
2121ae349f5Scvs2svn {
2137308ec68SBrian Somers   /* Send Term ACK please */
2141ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpSendTerminateAck\n");
2151ae349f5Scvs2svn   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
2161ae349f5Scvs2svn }
2171ae349f5Scvs2svn 
218503a7782SBrian Somers static void
2191ae349f5Scvs2svn CcpRecvResetReq(struct fsm *fp)
2201ae349f5Scvs2svn {
2217308ec68SBrian Somers   /* Got a reset REQ, reset outgoing dictionary */
222aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
22383d1af55SBrian Somers   if (ccp->out_init)
22483d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Reset)();
2251ae349f5Scvs2svn }
2261ae349f5Scvs2svn 
2271ae349f5Scvs2svn static void
2281ae349f5Scvs2svn CcpLayerStart(struct fsm *fp)
2291ae349f5Scvs2svn {
2307308ec68SBrian Somers   /* We're about to start up ! */
2311ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerStart.\n");
2321ae349f5Scvs2svn }
2331ae349f5Scvs2svn 
2341ae349f5Scvs2svn static void
2351ae349f5Scvs2svn CcpLayerFinish(struct fsm *fp)
2361ae349f5Scvs2svn {
2377308ec68SBrian Somers   /* We're now down */
238aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2391ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerFinish.\n");
24083d1af55SBrian Somers   if (ccp->in_init) {
24183d1af55SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Term)();
24283d1af55SBrian Somers     ccp->in_init = 0;
2437308ec68SBrian Somers   }
24483d1af55SBrian Somers   if (ccp->out_init) {
24583d1af55SBrian Somers     (*algorithm[ccp->out_algorithm]->o.Term)();
24683d1af55SBrian Somers     ccp->out_init = 0;
2477308ec68SBrian Somers   }
2481ae349f5Scvs2svn }
2491ae349f5Scvs2svn 
2501ae349f5Scvs2svn static void
2511ae349f5Scvs2svn CcpLayerDown(struct fsm *fp)
2521ae349f5Scvs2svn {
2537308ec68SBrian Somers   /* About to come down */
2541ae349f5Scvs2svn   LogPrintf(LogCCP, "CcpLayerDown.\n");
2551ae349f5Scvs2svn }
2561ae349f5Scvs2svn 
2571ae349f5Scvs2svn /*
2581ae349f5Scvs2svn  *  Called when CCP has reached the OPEN state
2591ae349f5Scvs2svn  */
2601ae349f5Scvs2svn static void
2611ae349f5Scvs2svn CcpLayerUp(struct fsm *fp)
2621ae349f5Scvs2svn {
2637308ec68SBrian Somers   /* We're now up */
264aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
265455aabc3SBrian Somers   LogPrintf(LogCCP, "CcpLayerUp.\n");
26683d1af55SBrian Somers   if (!ccp->in_init && ccp->in_algorithm >= 0 &&
26783d1af55SBrian Somers       ccp->in_algorithm < NALGORITHMS)
26883d1af55SBrian Somers     if ((*algorithm[ccp->in_algorithm]->i.Init)())
26983d1af55SBrian Somers       ccp->in_init = 1;
270247ab36dSBrian Somers     else {
271247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (in) initialisation failure\n",
27283d1af55SBrian Somers                 protoname(ccp->his_proto));
27383d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
274247ab36dSBrian Somers       FsmClose(fp);
275247ab36dSBrian Somers     }
27683d1af55SBrian Somers   if (!ccp->out_init && ccp->out_algorithm >= 0 &&
27783d1af55SBrian Somers       ccp->out_algorithm < NALGORITHMS)
27883d1af55SBrian Somers     if ((*algorithm[ccp->out_algorithm]->o.Init)())
27983d1af55SBrian Somers       ccp->out_init = 1;
280247ab36dSBrian Somers     else {
281247ab36dSBrian Somers       LogPrintf(LogERROR, "%s (out) initialisation failure\n",
28283d1af55SBrian Somers                 protoname(ccp->my_proto));
28383d1af55SBrian Somers       ccp->his_proto = ccp->my_proto = -1;
284247ab36dSBrian Somers       FsmClose(fp);
285247ab36dSBrian Somers     }
2861ae349f5Scvs2svn   LogPrintf(LogCCP, "Out = %s[%d], In = %s[%d]\n",
28783d1af55SBrian Somers             protoname(ccp->my_proto), ccp->my_proto,
28883d1af55SBrian Somers             protoname(ccp->his_proto), ccp->his_proto);
2891ae349f5Scvs2svn }
2901ae349f5Scvs2svn 
2911ae349f5Scvs2svn static void
29283d1af55SBrian Somers CcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type)
2931ae349f5Scvs2svn {
2947308ec68SBrian Somers   /* Deal with incoming data */
295aad81d1eSBrian Somers   struct ccp *ccp = fsm2ccp(fp);
2961ae349f5Scvs2svn   int type, length;
2971ae349f5Scvs2svn   int f;
2981ae349f5Scvs2svn 
2991ae349f5Scvs2svn   ackp = AckBuff;
3001ae349f5Scvs2svn   nakp = NakBuff;
3011ae349f5Scvs2svn   rejp = RejBuff;
3021ae349f5Scvs2svn 
3031ae349f5Scvs2svn   while (plen >= sizeof(struct fsmconfig)) {
3041ae349f5Scvs2svn     type = *cp;
3051ae349f5Scvs2svn     length = cp[1];
3061ae349f5Scvs2svn     if (type < NCFTYPES)
3071ae349f5Scvs2svn       LogPrintf(LogCCP, " %s[%d]\n", cftypes[type], length);
3081ae349f5Scvs2svn     else
3091ae349f5Scvs2svn       LogPrintf(LogCCP, " ???[%d]\n", length);
3101ae349f5Scvs2svn 
3111ae349f5Scvs2svn     for (f = NALGORITHMS-1; f > -1; f--)
3121ae349f5Scvs2svn       if (algorithm[f]->id == type)
3131ae349f5Scvs2svn         break;
3141ae349f5Scvs2svn 
3151ae349f5Scvs2svn     if (f == -1) {
3161ae349f5Scvs2svn       /* Don't understand that :-( */
3171ae349f5Scvs2svn       if (mode_type == MODE_REQ) {
31883d1af55SBrian Somers         ccp->my_reject |= (1 << type);
3191ae349f5Scvs2svn         memcpy(rejp, cp, length);
3201ae349f5Scvs2svn         rejp += length;
3211ae349f5Scvs2svn       }
3221ae349f5Scvs2svn     } else {
3231ae349f5Scvs2svn       struct lcp_opt o;
3241ae349f5Scvs2svn 
3251ae349f5Scvs2svn       switch (mode_type) {
3261ae349f5Scvs2svn       case MODE_REQ:
32783d1af55SBrian Somers 	if (Acceptable(algorithm[f]->Conf) && ccp->in_algorithm == -1) {
3281ae349f5Scvs2svn 	  memcpy(&o, cp, length);
3291ae349f5Scvs2svn           switch ((*algorithm[f]->i.Set)(&o)) {
3301ae349f5Scvs2svn           case MODE_REJ:
3311ae349f5Scvs2svn 	    memcpy(rejp, &o, o.len);
3321ae349f5Scvs2svn 	    rejp += o.len;
3331ae349f5Scvs2svn             break;
3341ae349f5Scvs2svn           case MODE_NAK:
3351ae349f5Scvs2svn 	    memcpy(nakp, &o, o.len);
3361ae349f5Scvs2svn 	    nakp += o.len;
3371ae349f5Scvs2svn             break;
3381ae349f5Scvs2svn           case MODE_ACK:
3391ae349f5Scvs2svn 	    memcpy(ackp, cp, length);
3401ae349f5Scvs2svn 	    ackp += length;
34183d1af55SBrian Somers 	    ccp->his_proto = type;
34283d1af55SBrian Somers             ccp->in_algorithm = f;		/* This one'll do ! */
3431ae349f5Scvs2svn             break;
3441ae349f5Scvs2svn           }
3451ae349f5Scvs2svn 	} else {
3461ae349f5Scvs2svn 	  memcpy(rejp, cp, length);
3471ae349f5Scvs2svn 	  rejp += length;
3481ae349f5Scvs2svn 	}
3491ae349f5Scvs2svn 	break;
3501ae349f5Scvs2svn       case MODE_NAK:
3511ae349f5Scvs2svn 	memcpy(&o, cp, length);
3521ae349f5Scvs2svn         if ((*algorithm[f]->o.Set)(&o) == MODE_ACK)
35383d1af55SBrian Somers           ccp->my_proto = algorithm[f]->id;
3541ae349f5Scvs2svn         else {
35583d1af55SBrian Somers 	  ccp->his_reject |= (1 << type);
35683d1af55SBrian Somers 	  ccp->my_proto = -1;
3571ae349f5Scvs2svn         }
3581ae349f5Scvs2svn         break;
3591ae349f5Scvs2svn       case MODE_REJ:
36083d1af55SBrian Somers 	ccp->his_reject |= (1 << type);
36183d1af55SBrian Somers 	ccp->my_proto = -1;
3621ae349f5Scvs2svn 	break;
3631ae349f5Scvs2svn       }
3641ae349f5Scvs2svn     }
3651ae349f5Scvs2svn 
3661ae349f5Scvs2svn     plen -= length;
3671ae349f5Scvs2svn     cp += length;
3681ae349f5Scvs2svn   }
3691ae349f5Scvs2svn 
3701ae349f5Scvs2svn   if (rejp != RejBuff) {
3711ae349f5Scvs2svn     ackp = AckBuff;	/* let's not send both ! */
37283d1af55SBrian Somers     if (!ccp->in_init) {
37383d1af55SBrian Somers       ccp->his_proto = -1;
37483d1af55SBrian Somers       ccp->in_algorithm = -1;
375247ab36dSBrian Somers     }
3761ae349f5Scvs2svn   }
3771ae349f5Scvs2svn }
3781ae349f5Scvs2svn 
3791ae349f5Scvs2svn void
380f4768038SBrian Somers CcpInput(struct ccp *ccp, struct bundle *bundle, struct mbuf *bp)
3811ae349f5Scvs2svn {
3827308ec68SBrian Somers   /* Got PROTO_CCP from link */
383455aabc3SBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
384f4768038SBrian Somers     FsmInput(&ccp->fsm, bp);
385455aabc3SBrian Somers   else if (bundle_Phase(bundle) < PHASE_NETWORK) {
386455aabc3SBrian Somers     LogPrintf(LogCCP, "Error: Unexpected CCP in phase %s (ignored)\n",
387455aabc3SBrian Somers               bundle_PhaseName(bundle));
3881ae349f5Scvs2svn     pfree(bp);
3891ae349f5Scvs2svn   }
3901ae349f5Scvs2svn }
3911ae349f5Scvs2svn 
392503a7782SBrian Somers static void
393503a7782SBrian Somers CcpRecvResetAck(struct fsm *fp, u_char id)
3941ae349f5Scvs2svn {
3957308ec68SBrian Somers   /* Got a reset ACK, reset incoming dictionary */
396f4768038SBrian Somers   struct ccp *ccp = fsm2ccp(fp);
397f4768038SBrian Somers 
398f4768038SBrian Somers   if (ccp->reset_sent != -1) {
399f4768038SBrian Somers     if (id != ccp->reset_sent) {
4001ae349f5Scvs2svn       LogPrintf(LogWARN, "CCP: Incorrect ResetAck (id %d, not %d) ignored\n",
401f4768038SBrian Somers                 id, ccp->reset_sent);
4021ae349f5Scvs2svn       return;
4031ae349f5Scvs2svn     }
4041ae349f5Scvs2svn     /* Whaddaya know - a correct reset ack */
405f4768038SBrian Somers   } else if (id == ccp->last_reset)
4061ae349f5Scvs2svn     LogPrintf(LogCCP, "Duplicate ResetAck (resetting again)\n");
4071ae349f5Scvs2svn   else {
4081ae349f5Scvs2svn     LogPrintf(LogWARN, "CCP: Unexpected ResetAck (id %d) ignored\n", id);
4091ae349f5Scvs2svn     return;
4101ae349f5Scvs2svn   }
4111ae349f5Scvs2svn 
412f4768038SBrian Somers   ccp->last_reset = ccp->reset_sent;
413f4768038SBrian Somers   ccp->reset_sent = -1;
414f4768038SBrian Somers   if (ccp->in_init)
415f4768038SBrian Somers     (*algorithm[ccp->in_algorithm]->i.Reset)();
4161ae349f5Scvs2svn }
4171ae349f5Scvs2svn 
4181ae349f5Scvs2svn int
419503a7782SBrian Somers ccp_Output(struct ccp *ccp, struct link *l, int pri, u_short proto,
420503a7782SBrian Somers            struct mbuf *m)
4211ae349f5Scvs2svn {
422503a7782SBrian Somers   /* Compress outgoing Network Layer data */
423503a7782SBrian Somers   if ((proto & 0xfff1) == 0x21 && ccp->fsm.state == ST_OPENED && ccp->out_init)
424f4768038SBrian Somers     return (*algorithm[ccp->out_algorithm]->o.Write)(ccp, l, pri, proto, m);
4251ae349f5Scvs2svn   return 0;
4261ae349f5Scvs2svn }
4271ae349f5Scvs2svn 
4281ae349f5Scvs2svn struct mbuf *
429503a7782SBrian Somers ccp_Decompress(struct ccp *ccp, u_short *proto, struct mbuf *bp)
4301ae349f5Scvs2svn {
431ee6c193fSBrian Somers   /*
432ee6c193fSBrian Somers    * If proto isn't PROTO_COMPD, we still want to pass it to the
433ee6c193fSBrian Somers    * decompression routines so that the dictionary's updated
434ee6c193fSBrian Somers    */
435503a7782SBrian Somers   if (ccp->fsm.state == ST_OPENED)
436ee6c193fSBrian Somers     if (*proto == PROTO_COMPD) {
4377308ec68SBrian Somers       /* Decompress incoming data */
438503a7782SBrian Somers       if (ccp->reset_sent != -1) {
4391ae349f5Scvs2svn         /* Send another REQ and put the packet in the bit bucket */
440503a7782SBrian Somers         LogPrintf(LogCCP, "ReSendResetReq(%d)\n", ccp->reset_sent);
441503a7782SBrian Somers         FsmOutput(&ccp->fsm, CODE_RESETREQ, ccp->reset_sent, NULL, 0);
442503a7782SBrian Somers       } else if (ccp->in_init)
443f4768038SBrian Somers         return (*algorithm[ccp->in_algorithm]->i.Read)(ccp, proto, bp);
444ee6c193fSBrian Somers       pfree(bp);
445ee6c193fSBrian Somers       bp = NULL;
446503a7782SBrian Somers     } else if ((*proto & 0xfff1) == 0x21 && ccp->in_init)
447ee6c193fSBrian Somers       /* Add incoming Network Layer traffic to our dictionary */
448f4768038SBrian Somers       (*algorithm[ccp->in_algorithm]->i.DictSetup)(ccp, *proto, bp);
4491ae349f5Scvs2svn 
450ee6c193fSBrian Somers   return bp;
4511ae349f5Scvs2svn }
452